okf 1.0.0 → 1.1.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.
- checksums.yaml +4 -4
- data/.okf/capabilities/graph-server.md +13 -10
- data/.okf/capabilities/library-api.md +6 -1
- data/.okf/design/index.md +1 -1
- data/.okf/design/server-trust-boundary.md +20 -15
- data/.okf/log.md +1 -0
- data/.okf/overview.md +10 -9
- data/CHANGELOG.md +15 -0
- data/README.md +133 -29
- data/exe/okf +2 -0
- data/lib/okf/cli.rb +2 -0
- data/lib/okf/server/templates/graph.html.erb +2 -1
- data/lib/okf/version.rb +1 -1
- data/lib/okf.rb +0 -3
- metadata +10 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 464529d862280b3385f00fa36a309c81fa03f71db2d2534f11707a04fdca4679
|
|
4
|
+
data.tar.gz: 1487c71ef1e70340d0a6212b85f0202ae287c0a1df7b59489f643bdbf63dd05f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6240c78b9b1c23b64c97f980db2aabe5d3126eb0c69e4eb853381bed2e5e1be991a4835c62a806cfb5e219fdb4b3bf4bf3ef8960063d6f30d5fcf2aaf630d8d2
|
|
7
|
+
data.tar.gz: 32d943f353984a9d6e7224c881169bf851008976adee4ef6e785878372f225162f4359021b2ab576cf0615dde0b23054b61826ee39b8937356e1759d0dbca0c4
|
|
@@ -4,14 +4,15 @@ title: Interactive graph server (server)
|
|
|
4
4
|
description: A self-contained HTML knowledge graph served over HTTP, and a mountable Rack app.
|
|
5
5
|
resource: lib/okf/server/app.rb
|
|
6
6
|
tags: [server, graph, rack, diagram]
|
|
7
|
-
timestamp: 2026-07-
|
|
7
|
+
timestamp: 2026-07-12T12:00:00Z
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Overview
|
|
11
11
|
|
|
12
12
|
`okf server` boots an interactive view of the [graph](../model/graph.md):
|
|
13
13
|
`OKF::Server::App` is a Rack app that serves one self-contained HTML page which
|
|
14
|
-
draws the bundle with Cytoscape and renders concept bodies with marked
|
|
14
|
+
draws the bundle with Cytoscape and renders concept bodies with marked, sanitized
|
|
15
|
+
by DOMPurify. Because
|
|
15
16
|
it is a plain Rack app, it also mounts inside a host application (e.g. a Rails
|
|
16
17
|
route) — the built-in WEBrick runner is just the default, injected so tests drive
|
|
17
18
|
it without opening a socket.
|
|
@@ -19,8 +20,9 @@ it without opening a socket.
|
|
|
19
20
|
# The page stays self-contained
|
|
20
21
|
|
|
21
22
|
One ERB template, inline CSS and JS, no build step and no bundler. The only
|
|
22
|
-
external assets are Cytoscape and
|
|
23
|
-
only when a concept body actually contains a diagram; everything else
|
|
23
|
+
external assets are Cytoscape, marked, and DOMPurify from a CDN — plus Mermaid,
|
|
24
|
+
lazy-loaded only when a concept body actually contains a diagram; everything else
|
|
25
|
+
is inlined.
|
|
24
26
|
The graph draws from a **minimal** node payload and pulls each concept's body
|
|
25
27
|
**on demand** via `fetch()`, which is why even a large bundle loads fast.
|
|
26
28
|
|
|
@@ -35,7 +37,7 @@ sequenceDiagram
|
|
|
35
37
|
Note over A,B: angle brackets escaped (json_for_script) — safe
|
|
36
38
|
B->>A: GET /node?id=… (on demand)
|
|
37
39
|
A-->>B: concept Markdown body
|
|
38
|
-
Note over A,B: marked renders it
|
|
40
|
+
Note over A,B: marked renders it, DOMPurify sanitizes it — safe
|
|
39
41
|
```
|
|
40
42
|
|
|
41
43
|
# Endpoints
|
|
@@ -49,11 +51,12 @@ sequenceDiagram
|
|
|
49
51
|
|
|
50
52
|
# Trust boundary
|
|
51
53
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
`
|
|
55
|
-
|
|
56
|
-
[server trust boundary](../design/server-trust-boundary.md) for
|
|
54
|
+
Both paths into the page are guarded. Inlined data goes through `json_for_script`,
|
|
55
|
+
which escapes `<` so it cannot break out of its `<script>`; each fetched body is
|
|
56
|
+
run through `DOMPurify.sanitize(marked.parse(...))`, which strips any script or
|
|
57
|
+
handler before it reaches the DOM. See the
|
|
58
|
+
[server trust boundary](../design/server-trust-boundary.md) for what that does and
|
|
59
|
+
does not cover.
|
|
57
60
|
|
|
58
61
|
# Citations
|
|
59
62
|
|
|
@@ -4,7 +4,7 @@ title: Library API
|
|
|
4
4
|
description: The Ruby surface — a pure in-memory model plus on-disk handles, an "ActiveRecord for the filesystem".
|
|
5
5
|
resource: lib/okf.rb
|
|
6
6
|
tags: [library, api, ruby, diagram]
|
|
7
|
-
timestamp: 2026-07-
|
|
7
|
+
timestamp: 2026-07-12T12:00:00Z
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Overview
|
|
@@ -18,6 +18,11 @@ gives you two layers, split cleanly by the [core/shell rule](../design/core-shel
|
|
|
18
18
|
- **on-disk handles** — `OKF::Concept::File` and `OKF::Bundle::Folder`, which add
|
|
19
19
|
`load` / `save` / `reload` / `delete` on top of the pure model.
|
|
20
20
|
|
|
21
|
+
`require "okf"` stops at those two layers: the [CLI](../cli.md) and the skill
|
|
22
|
+
installer load only when asked for (from `exe/okf`, or an explicit
|
|
23
|
+
`require "okf/cli"` / `require "okf/skill"`), so an app embedding the library
|
|
24
|
+
never drags in the command-line machinery.
|
|
25
|
+
|
|
21
26
|
```mermaid
|
|
22
27
|
classDiagram
|
|
23
28
|
class Concept {
|
data/.okf/design/index.md
CHANGED
|
@@ -7,4 +7,4 @@ the code looks the way it does.
|
|
|
7
7
|
* [Core/shell split](core-shell-split.md) - pure logic must never touch disk, stdio, or the shell layer; a test enforces it.
|
|
8
8
|
* [Ruby 2.4 floor](ruby-floor.md) - runs on the Ruby an OS already ships; newer APIs are banned.
|
|
9
9
|
* [Runtime dependencies](runtime-dependencies.md) - exactly `rack` and `webrick`, no ActiveSupport.
|
|
10
|
-
* [Server trust boundary](server-trust-boundary.md) - the served page
|
|
10
|
+
* [Server trust boundary](server-trust-boundary.md) - the served page sanitizes concept bodies and escapes inlined data; both XSS paths are closed.
|
|
@@ -1,35 +1,40 @@
|
|
|
1
1
|
---
|
|
2
2
|
type: Constraint
|
|
3
3
|
title: The server trust boundary
|
|
4
|
-
description: The served page
|
|
4
|
+
description: The served page sanitizes each concept body before rendering and escapes inlined data, so both XSS paths into the page are closed.
|
|
5
5
|
resource: lib/okf/server/templates/graph.html.erb
|
|
6
6
|
tags: [security, server, xss]
|
|
7
|
-
timestamp: 2026-07-
|
|
7
|
+
timestamp: 2026-07-12T12:00:00Z
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Overview
|
|
11
11
|
|
|
12
|
-
The [graph server](../capabilities/graph-server.md)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
is simple: **only serve bundles you trust.**
|
|
12
|
+
The [graph server](../capabilities/graph-server.md) renders whatever bundle you
|
|
13
|
+
point it at, and a bundle is just files, so the page has to assume a body might
|
|
14
|
+
carry active content. Two defenses handle that — one for each path into the page.
|
|
16
15
|
|
|
17
16
|
# Where the boundary sits
|
|
18
17
|
|
|
19
|
-
There are two
|
|
18
|
+
There are two data paths into the page, and each carries its own guard:
|
|
20
19
|
|
|
21
20
|
| Path | Handling | Safe? |
|
|
22
21
|
|------|----------|-------|
|
|
23
22
|
| Graph data **inlined** into the page | through `json_for_script`, which escapes `<` | yes — it cannot break out of its `<script>` |
|
|
24
|
-
| Concept bodies **fetched** on demand (`/node?id=`) |
|
|
23
|
+
| Concept bodies **fetched** on demand (`/node?id=`) | `marked` renders the Markdown, then `DOMPurify.sanitize` scrubs it before it reaches the DOM | yes — scripts, handlers, and `javascript:` URLs are stripped |
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
The [description](../format/cross-links.md) shown in the inspector takes a third
|
|
26
|
+
path and never needs the client's help: the server escapes it
|
|
27
|
+
(`OKF::Server::App#description_fragment`) before sending it, so it arrives inert.
|
|
28
|
+
|
|
29
|
+
# What sanitizing does not cover
|
|
30
|
+
|
|
31
|
+
DOMPurify removes the code, not the content. The page still fetches and shows the
|
|
32
|
+
links, images, and Mermaid diagrams a body names (Mermaid runs in its `strict`
|
|
33
|
+
mode), and it pulls Cytoscape, marked, and DOMPurify from a CDN. So the rule is no
|
|
34
|
+
longer *only serve bundles you trust* — it is the ordinary care you would give any
|
|
35
|
+
document from a source you do not know.
|
|
31
36
|
|
|
32
37
|
# Citations
|
|
33
38
|
|
|
34
|
-
[1] [README.md — Server trust boundary](https://github.com/serradura/okf-gem/blob/main/README.md) — the
|
|
35
|
-
[2] [lib/okf/server/templates/graph.html.erb](https://github.com/serradura/okf-gem/blob/main/lib/okf/server/templates/graph.html.erb) — `json_for_script` and the
|
|
39
|
+
[1] [README.md — Server trust boundary](https://github.com/serradura/okf-gem/blob/main/README.md) — the two-defense summary.
|
|
40
|
+
[2] [lib/okf/server/templates/graph.html.erb](https://github.com/serradura/okf-gem/blob/main/lib/okf/server/templates/graph.html.erb) — `json_for_script` and the `DOMPurify.sanitize(marked.parse(...))` render.
|
data/.okf/log.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Update Log
|
|
2
2
|
|
|
3
3
|
## 2026-07-12
|
|
4
|
+
* **Sync**: caught the bundle up with the gem at 1.1.0 — the [graph server](capabilities/graph-server.md) now sanitizes each fetched body with DOMPurify before rendering, so the [server trust boundary](design/server-trust-boundary.md) closes the on-demand render path (its [design listing](design/) reworded to match), and the [library API](capabilities/library-api.md) notes that `require "okf"` loads the library alone now that the CLI and skill load on demand.
|
|
4
5
|
* **Sync**: caught the bundle up with the CLI at 1.0.0 — documented the new `index` command (the §6 progressive-disclosure map, the read view that sees the reserved `index.md` layer), compact-by-default JSON with `--pretty`, and `--fields`/`--except` projection on the list views, in [read views](capabilities/read-views.md) plus the `index`-verb enumerations in the [CLI](cli.md), the [overview](overview.md), and the [capabilities](capabilities/) index listing.
|
|
5
6
|
|
|
6
7
|
## 2026-07-11
|
data/.okf/overview.md
CHANGED
|
@@ -15,8 +15,9 @@ gives you leverage over knowledge that already lives as Markdown.
|
|
|
15
15
|
|
|
16
16
|
```mermaid
|
|
17
17
|
flowchart LR
|
|
18
|
-
skill["companion<br/>agent skill"] -. authors .-> bundle[("OKF v0.1 bundle<br/>Markdown + YAML")]
|
|
18
|
+
skill["companion<br/>agent skill"] -. authors/curate .-> bundle[("OKF v0.1 bundle<br/>Markdown + YAML")]
|
|
19
19
|
bundle --> model["pure model<br/>Concept · Bundle · Graph"]
|
|
20
|
+
skill -. execute .-> cli
|
|
20
21
|
subgraph cli ["okf CLI"]
|
|
21
22
|
validate["validate — legal? §9"]
|
|
22
23
|
lint["lint — well-curated?"]
|
|
@@ -29,13 +30,13 @@ flowchart LR
|
|
|
29
30
|
Over such a bundle the gem gives you five capabilities behind one
|
|
30
31
|
[command-line tool](cli.md):
|
|
31
32
|
|
|
32
|
-
| Capability
|
|
33
|
-
|
|
34
|
-
| [
|
|
35
|
-
| [
|
|
36
|
-
| [
|
|
37
|
-
| [
|
|
38
|
-
| [
|
|
33
|
+
| Capability | What it answers | Verb |
|
|
34
|
+
| -------------------------------------------------------- | --------------------------------- | ---------------- |
|
|
35
|
+
| [Companion agent skill](capabilities/agent-skill.md) | Can an agent author it? | `skill` |
|
|
36
|
+
| [Conformance validator](capabilities/validator.md) | Is this a legal OKF bundle? (§9) | `validate` |
|
|
37
|
+
| [Curation linter](capabilities/linter.md) | Is it navigable, complete, fresh? | `lint` / `loose` |
|
|
38
|
+
| [Interactive graph server](capabilities/graph-server.md) | Can I explore it visually? | `server` |
|
|
39
|
+
| [Library API](capabilities/library-api.md) | Can my Ruby program use it? | (in-process) |
|
|
39
40
|
|
|
40
41
|
Alongside those, a family of [read views](capabilities/read-views.md) —
|
|
41
42
|
`index`, `catalog`, `files`, `tags`, `stats`, `graph` — print the bundle at a
|
|
@@ -43,7 +44,7 @@ glance so an agent reads it without a browser.
|
|
|
43
44
|
|
|
44
45
|
# The two ideas it inherits from the format
|
|
45
46
|
|
|
46
|
-
- **Dual audience.** Every file serves a human skimming it
|
|
47
|
+
- **Dual audience.** Every file serves a human skimming it _and_ an agent
|
|
47
48
|
extracting from it, so bodies are structural Markdown and
|
|
48
49
|
[links](format/cross-links.md) are plain Markdown links — both readers already
|
|
49
50
|
understand them.
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.1.0] - 2026-07-12
|
|
4
|
+
|
|
5
|
+
- The graph server now sanitizes every concept body before rendering it. The
|
|
6
|
+
page runs marked's HTML output through [DOMPurify](https://github.com/cure53/DOMPurify)
|
|
7
|
+
(loaded from the same CDN as Cytoscape and marked) on the way to the DOM, so a
|
|
8
|
+
bundle carrying active content in a Markdown body can no longer script the
|
|
9
|
+
viewer. Inlined graph data was already escaped through `json_for_script`; this
|
|
10
|
+
closes the other path.
|
|
11
|
+
- `require "okf"` now loads the pure library only. The two argv-facing shells —
|
|
12
|
+
`OKF::CLI` and the `OKF::Skill` installer — load on demand, from `exe/okf` or
|
|
13
|
+
an explicit `require "okf/cli"` / `require "okf/skill"`. `optparse` moves with
|
|
14
|
+
the CLI, so an embedding app (e.g. a Rails store) that only reaches for the
|
|
15
|
+
in-memory model and on-disk handles no longer pulls in the command-line
|
|
16
|
+
machinery. The CLI itself is unchanged.
|
|
17
|
+
|
|
3
18
|
## [1.0.0] - 2026-07-12
|
|
4
19
|
|
|
5
20
|
Initial release.
|
data/README.md
CHANGED
|
@@ -5,17 +5,59 @@
|
|
|
5
5
|
</h1>
|
|
6
6
|
</p>
|
|
7
7
|
|
|
8
|
-
>
|
|
9
|
-
>
|
|
10
|
-
>
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
8
|
+
<p align="center">
|
|
9
|
+
<i>A lightweight Ruby gem for OKF: author, curate, and serve bundles as an interactive graph.</i>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://rubygems.org/gems/okf"><img src="https://img.shields.io/gem/v/okf" alt="Gem version"></a>
|
|
14
|
+
<a href="https://rubygems.org/gems/okf"><img src="https://img.shields.io/gem/dt/okf" alt="Downloads"></a>
|
|
15
|
+
<a href="https://github.com/serradura/okf-gem/actions/workflows/main.yml"><img src="https://github.com/serradura/okf-gem/actions/workflows/main.yml/badge.svg" alt="CI"></a>
|
|
16
|
+
<a href="https://github.com/serradura/okf-gem"><img src="https://img.shields.io/badge/ruby-%3E%3D%202.4-black" alt="Ruby >= 2.4"></a>
|
|
17
|
+
<a href="LICENSE.txt"><img src="https://img.shields.io/badge/license-Apache--2.0-blue" alt="License: Apache-2.0"></a>
|
|
18
|
+
<a href="lib/okf/skill/reference/SPEC.md"><img src="https://img.shields.io/badge/OKF-v0.1-6E56CF" alt="OKF v0.1"></a>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
**okf-gem** — `okf` on RubyGems — reads, validates, lints, and serves
|
|
22
|
+
**Open Knowledge Format (OKF)** v0.1 bundles: directories of Markdown files with YAML frontmatter that humans and agents read from one source. It does not define a new place to keep knowledge; it gives you leverage over knowledge that already lives as Markdown. Each file is a _concept_; a directory of them is a _bundle_.
|
|
23
|
+
|
|
24
|
+
Here is what it is able to do:
|
|
25
|
+
|
|
26
|
+
```mermaid
|
|
27
|
+
flowchart LR
|
|
28
|
+
skill["companion<br/>agent skill"] -. authors/curate .-> bundle[("OKF v0.1 bundle<br/>Markdown + YAML")]
|
|
29
|
+
bundle --> model["pure model<br/>Concept · Bundle · Graph"]
|
|
30
|
+
skill -. execute .-> cli
|
|
31
|
+
subgraph cli ["okf CLI"]
|
|
32
|
+
validate["validate — legal? §9"]
|
|
33
|
+
lint["lint — well-curated?"]
|
|
34
|
+
server["server — explore"]
|
|
35
|
+
end
|
|
36
|
+
model --> cli
|
|
37
|
+
model --> library["library API<br/>embed in Ruby"]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Over a bundle the gem gives you the `okf`
|
|
41
|
+
command-line tool (the library API is also usable in-process). Each capability
|
|
42
|
+
below links to the concept that documents it: this gem's own knowledge is an OKF
|
|
43
|
+
bundle, so you can read its design in the format it defends.
|
|
44
|
+
|
|
45
|
+
| Capability | What it answers | Verb |
|
|
46
|
+
| ------------------------------------------------------------- | --------------------------------- | ---------------- |
|
|
47
|
+
| [Companion agent skill](.okf/capabilities/agent-skill.md) | Can an agent author it? | `skill` |
|
|
48
|
+
| [Conformance validator](.okf/capabilities/validator.md) | Is this a legal OKF bundle? (§9) | `validate` |
|
|
49
|
+
| [Curation linter](.okf/capabilities/linter.md) | Is it navigable, complete, fresh? | `lint` / `loose` |
|
|
50
|
+
| [Interactive graph server](.okf/capabilities/graph-server.md) | Can I explore it visually? | `server` |
|
|
51
|
+
| [Library API](.okf/capabilities/library-api.md) | Can my Ruby program use it? | in-process |
|
|
52
|
+
|
|
53
|
+
> [!TIP]
|
|
54
|
+
> **Browse the gem as knowledge, not just docs.** This README is the front door;
|
|
55
|
+
> the depth lives in the [`.okf/`](.okf) bundle this repo ships. Start at the
|
|
56
|
+
> [overview](.okf/overview.md), then follow the graph into the
|
|
57
|
+
> [capabilities](.okf/capabilities/) (what it does), the
|
|
58
|
+
> [design constraints](.okf/design/) (why it stays this light), and the
|
|
59
|
+
> [format itself](.okf/format/) (what it operates on). Run `okf server .okf` to
|
|
60
|
+
> walk the same bundle as an interactive graph.
|
|
19
61
|
|
|
20
62
|
It is deliberately light so it runs on the Ruby your OS already ships:
|
|
21
63
|
|
|
@@ -23,7 +65,57 @@ It is deliberately light so it runs on the Ruby your OS already ships:
|
|
|
23
65
|
its core dependency;
|
|
24
66
|
- only two runtime dependencies: `rack` (the server is a mountable Rack app)
|
|
25
67
|
and `webrick` (unbundled from Ruby in 3.0);
|
|
26
|
-
- no ActiveSupport, no build step, no JavaScript toolchain
|
|
68
|
+
- no ActiveSupport, no build step, no JavaScript toolchain — the
|
|
69
|
+
[design constraints](.okf/design/) that hold this line are enforced by tests.
|
|
70
|
+
|
|
71
|
+
## Why OKF
|
|
72
|
+
|
|
73
|
+
Project knowledge (why a service exists, what a metric really measures, the
|
|
74
|
+
reasoning a schema encodes) lives scattered across wikis, code comments, and
|
|
75
|
+
whoever happened to be in the room, and an agent re-derives it every session. OKF
|
|
76
|
+
gives it one durable, diffable home, versioned next to the code it describes and
|
|
77
|
+
read from the same file by people and agents alike. [OKF][okf] is an open,
|
|
78
|
+
vendor-neutral format (Google Cloud, 2026); this gem is the Ruby-native way to
|
|
79
|
+
work with it.
|
|
80
|
+
|
|
81
|
+
[okf]: https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing
|
|
82
|
+
|
|
83
|
+
## What a bundle looks like
|
|
84
|
+
|
|
85
|
+
A bundle is just a directory; each concept is one Markdown file whose path is its
|
|
86
|
+
id. This repo documents _itself_ in OKF, so the tree below is real:
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
.okf/
|
|
90
|
+
├── index.md # progressive-disclosure map (root carries okf_version)
|
|
91
|
+
├── log.md # ISO-dated change history, newest first
|
|
92
|
+
├── overview.md
|
|
93
|
+
├── format/frontmatter.md
|
|
94
|
+
├── model/graph.md
|
|
95
|
+
└── capabilities/graph-server.md # one concept = one file
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The only hard requirement is YAML frontmatter with a non-empty `type`; everything
|
|
99
|
+
else is optional and tolerated when missing. A concept (here the real
|
|
100
|
+
`capabilities/graph-server.md`, body trimmed) reads:
|
|
101
|
+
|
|
102
|
+
```markdown
|
|
103
|
+
---
|
|
104
|
+
type: Capability
|
|
105
|
+
title: Interactive graph server (server)
|
|
106
|
+
description: A self-contained HTML knowledge graph served over HTTP, and a mountable Rack app.
|
|
107
|
+
resource: lib/okf/server/app.rb
|
|
108
|
+
tags: [server, graph, rack, diagram]
|
|
109
|
+
timestamp: 2026-07-11T12:00:00Z
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
# Overview
|
|
113
|
+
|
|
114
|
+
`okf server` boots an interactive view of the [graph](../model/graph.md) …
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
That bundle is this gem's own documentation. Clone the repo and run
|
|
118
|
+
`okf server .okf` to browse it as the graph diagrammed at the top of this file.
|
|
27
119
|
|
|
28
120
|
## Installation
|
|
29
121
|
|
|
@@ -56,10 +148,6 @@ okf --version
|
|
|
56
148
|
Exit codes: `0` success, `1` non-conformant bundle (or a `lint --fail-on`
|
|
57
149
|
threshold crossed), `2` usage error.
|
|
58
150
|
|
|
59
|
-
> [!NOTE]
|
|
60
|
-
> Section numbers like §5, §8, and §9 refer to the OKF v0.1 spec, bundled with
|
|
61
|
-
> the skill at [`lib/okf/skill/reference/SPEC.md`](lib/okf/skill/reference/SPEC.md).
|
|
62
|
-
|
|
63
151
|
```bash
|
|
64
152
|
$ okf validate docs
|
|
65
153
|
OKF v0.1 conformance — docs
|
|
@@ -82,11 +170,13 @@ _The graph server on this repo's own [`.okf`](.okf) bundle, with the
|
|
|
82
170
|
|
|
83
171
|
`graph` and `server` are best-effort (§9): a file with invalid frontmatter is
|
|
84
172
|
skipped (and noted on stderr), not fatal, so one bad file never breaks the rest.
|
|
85
|
-
|
|
86
|
-
[server trust boundary](#server-trust-boundary)
|
|
173
|
+
The [graph server](.okf/capabilities/graph-server.md) concept walks the request
|
|
174
|
+
flow and endpoints; the [server trust boundary](#server-trust-boundary) below
|
|
175
|
+
explains how the page handles a bundle you did not author.
|
|
87
176
|
|
|
88
|
-
`lint`
|
|
89
|
-
provenance, and hygiene)
|
|
177
|
+
`lint` (the [curation linter](.okf/capabilities/linter.md)) reports curation
|
|
178
|
+
quality (reachability, backlog, completeness, freshness, provenance, and hygiene)
|
|
179
|
+
separately from `validate`. It is advisory: it exits
|
|
90
180
|
`0` even with findings unless you opt into gating with `--fail-on warn`.
|
|
91
181
|
|
|
92
182
|
```bash
|
|
@@ -116,7 +206,8 @@ always exits `0`.
|
|
|
116
206
|
|
|
117
207
|
## Agent skill
|
|
118
208
|
|
|
119
|
-
The gem carries the companion OKF agent skill
|
|
209
|
+
The gem carries the [companion OKF agent skill](.okf/capabilities/agent-skill.md):
|
|
210
|
+
a `SKILL.md` plus reference
|
|
120
211
|
and template files that teach a coding agent to author, maintain, and consume OKF
|
|
121
212
|
bundles and to drive the commands above. Because the skill ships inside the gem,
|
|
122
213
|
installing the gem already puts the skill on your machine, and the skill's
|
|
@@ -139,7 +230,8 @@ is never clobbered.
|
|
|
139
230
|
|
|
140
231
|
## Library
|
|
141
232
|
|
|
142
|
-
The gem is two layers: pure
|
|
233
|
+
The gem (the [library API](.okf/capabilities/library-api.md)) is two layers: pure
|
|
234
|
+
in-memory data (`OKF::Concept`, `OKF::Bundle`)
|
|
143
235
|
you build, interrogate, and analyze with no disk involved, and on-disk
|
|
144
236
|
handles (`OKF::Concept::File`, `OKF::Bundle::Folder`) that add
|
|
145
237
|
load/save/reload/delete, an "ActiveRecord for the filesystem".
|
|
@@ -199,7 +291,8 @@ The lower-level pieces are usable on their own too: `OKF::Bundle::Validator.call
|
|
|
199
291
|
|
|
200
292
|
### Conformance model
|
|
201
293
|
|
|
202
|
-
`validate`
|
|
294
|
+
`validate` (the [conformance validator](.okf/capabilities/validator.md)) implements
|
|
295
|
+
the spec's [§9 conformance definition](lib/okf/skill/reference/SPEC.md#9-conformance)
|
|
203
296
|
exactly. There are three hard conditions, all errors:
|
|
204
297
|
|
|
205
298
|
- **§9.1** every non-reserved file has a parseable YAML frontmatter block;
|
|
@@ -236,12 +329,23 @@ is the structured input an agent consumes to reason about those.
|
|
|
236
329
|
|
|
237
330
|
## Server trust boundary
|
|
238
331
|
|
|
239
|
-
> [!
|
|
240
|
-
> The
|
|
241
|
-
>
|
|
242
|
-
>
|
|
243
|
-
>
|
|
244
|
-
>
|
|
332
|
+
> [!NOTE]
|
|
333
|
+
> The graph page defends against a bundle that carries active content in two
|
|
334
|
+
> places. It escapes any graph data inlined into the page (`<` becomes `<`),
|
|
335
|
+
> which keeps that data from breaking out of its `<script>`. And it fetches each
|
|
336
|
+
> concept body on demand, then runs marked's HTML output through
|
|
337
|
+
> [DOMPurify](https://github.com/cure53/DOMPurify) before it reaches the DOM, so
|
|
338
|
+
> a script or event handler hidden in a Markdown body is stripped rather than
|
|
339
|
+
> executed. Descriptions are escaped on the server.
|
|
340
|
+
>
|
|
341
|
+
> That covers the paths that could run code. The page still loads Cytoscape,
|
|
342
|
+
> marked, and DOMPurify from a CDN and renders whatever links and diagrams a body
|
|
343
|
+
> contains, so treat an unfamiliar bundle the way you would treat any document
|
|
344
|
+
> from a source you do not know.
|
|
345
|
+
|
|
346
|
+
The [server trust boundary](.okf/design/server-trust-boundary.md) concept has the
|
|
347
|
+
full write-up: the two data paths, what sanitizing does, and what it leaves to
|
|
348
|
+
your judgment.
|
|
245
349
|
|
|
246
350
|
## Development
|
|
247
351
|
|
data/exe/okf
CHANGED
data/lib/okf/cli.rb
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
12
12
|
<script src="https://cdn.jsdelivr.net/npm/cytoscape@3.30.2/dist/cytoscape.min.js"></script>
|
|
13
13
|
<script src="https://cdn.jsdelivr.net/npm/marked@14/marked.min.js"></script>
|
|
14
|
+
<script src="https://cdn.jsdelivr.net/npm/dompurify@3/dist/purify.min.js"></script>
|
|
14
15
|
<style>
|
|
15
16
|
:root{
|
|
16
17
|
--bg:#ffffff; --panel:#ffffff; --panel-2:#f6f7f8; --canvas:#f4f5f7; --ink:#1f2328; --ink-soft:#333333;
|
|
@@ -466,7 +467,7 @@ function rethemeMermaid(){if(!window.mermaid)return;const nodes=[...document.que
|
|
|
466
467
|
window.mermaid.initialize({startOnLoad:false,securityLevel:'strict',theme:isDark()?'dark':'default'});
|
|
467
468
|
nodes.forEach(d=>{if(d.dataset.src){d.removeAttribute('data-processed');d.innerHTML='';d.textContent=d.dataset.src;}});
|
|
468
469
|
window.mermaid.run({nodes}).catch(()=>{});}
|
|
469
|
-
function renderMarkdown(el,text){el.innerHTML=text?marked.parse(text):'<span class="empty">empty body</span>';processMermaid(el);}
|
|
470
|
+
function renderMarkdown(el,text){el.innerHTML=text?DOMPurify.sanitize(marked.parse(text)):'<span class="empty">empty body</span>';processMermaid(el);}
|
|
470
471
|
|
|
471
472
|
/* ── inspector ── */
|
|
472
473
|
const gbody=document.querySelector('.graph-body'), sideBody=document.getElementById('side-body');
|
data/lib/okf/version.rb
CHANGED
data/lib/okf.rb
CHANGED
|
@@ -4,7 +4,6 @@ require "erb"
|
|
|
4
4
|
require "fileutils"
|
|
5
5
|
require "date"
|
|
6
6
|
require "json"
|
|
7
|
-
require "optparse"
|
|
8
7
|
require "pathname"
|
|
9
8
|
require "securerandom"
|
|
10
9
|
require "set"
|
|
@@ -50,6 +49,4 @@ module OKF
|
|
|
50
49
|
require "okf/bundle/reader"
|
|
51
50
|
require "okf/bundle/writer"
|
|
52
51
|
require "okf/bundle/folder"
|
|
53
|
-
require "okf/skill"
|
|
54
|
-
require "okf/cli"
|
|
55
52
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: okf
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rodrigo Serradura
|
|
@@ -38,11 +38,13 @@ dependencies:
|
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
39
|
version: '1.4'
|
|
40
40
|
description: |
|
|
41
|
-
OKF is portable knowledge
|
|
42
|
-
humans and agents read. This gem
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
OKF (Open Knowledge Format) is portable knowledge: Markdown files with YAML
|
|
42
|
+
frontmatter that both humans and agents read from one source. This gem is the
|
|
43
|
+
Ruby-native way to work with it. Its companion agent skill authors and curates
|
|
44
|
+
a bundle; the `okf` command-line tool validates the result for v0.1 (§9)
|
|
45
|
+
conformance, lints its curation quality, and serves it as an interactive graph
|
|
46
|
+
(a mountable Rack app). The same validate, lint, and graph run in-process
|
|
47
|
+
through a library API (OKF::Bundle and friends).
|
|
46
48
|
email:
|
|
47
49
|
- rodrigo.serradura@gmail.com
|
|
48
50
|
executables:
|
|
@@ -138,5 +140,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
138
140
|
requirements: []
|
|
139
141
|
rubygems_version: 4.0.16
|
|
140
142
|
specification_version: 4
|
|
141
|
-
summary:
|
|
143
|
+
summary: 'A lightweight Ruby gem for OKF: author, curate, and serve bundles as an
|
|
144
|
+
interactive graph.'
|
|
142
145
|
test_files: []
|