# OKF reference demo 4 — serving and firewall

**The point:** the firewall is the endpoint, not the format. OKF encrypts nothing and access-controls nothing. An external agent can read a bundle's `index.md`, walk one level down, and read any Layer-2 concept — and when it follows a concept's `resource:` pointer to rehydrate the deep model without authorization, it gets HTTP 401. That contrast is the whole demo.

## The gated Worker

`okf-persona-gate` (Cloudflare Worker, `projects/shur/okf/serving/worker/`) serves the shuriq-jonny persona bundle two ways:

| Route | Access | Returns |
|---|---|---|
| `/` | open | endpoint map (JSON) |
| `/index.md` | open | the bundle root: every concept, grouped by type |
| `/<Type>/<id>.md` | open | one Layer-2 concept doc |
| `/rehydrate/<id>` | **Bearer token** | the deep model: typed edges, attributes, confidence |

Live at `https://okf-persona-gate.jonny-a6b.workers.dev`. The token is a Worker secret (`REHYDRATION_TOKEN`); the local copy lives at `projects/shur/okf/serving/.token` (gitignored). Production hardening would put Cloudflare Access in front of the gate as well; the bearer check is the demo-scale version of the same boundary.

## The contrast, captured live (2026-07-16)

```console
$ curl https://okf-persona-gate.jonny-a6b.workers.dev/Person/person-jonny.md
---
type: Person
title: Jonny
resource: https://okf-persona-gate.jonny-a6b.workers.dev/rehydrate/person-jonny
...                                    # HTTP 200 — Layer 2 is open

$ curl https://okf-persona-gate.jonny-a6b.workers.dev/rehydrate/person-jonny
{
 "error": "unauthorized",
 "detail": "The deep model for this entity (typed relationship edges, attribute
            values, confidence scores) resolves only for authorized agents."
}                                      # HTTP 401 — the firewall

$ curl -H "Authorization: Bearer $(cat serving/.token)" \
       https://okf-persona-gate.jonny-a6b.workers.dev/rehydrate/person-jonny
{
 "layer": 3,
 "entity": { "id": "person-jonny", "outgoing": [ { "target": "ShurIQ Brand
   Dashboard", "rel": "views_dashboard", "confidence": 0.92 } ], ... }
}                                      # HTTP 200 — same URL, authorized
```

## The MCP resource server (variant 2)

`projects/shur/okf/serving/okf_mcp_server.mjs` — a dependency-free stdio MCP server that lists every concept in the bundle as an MCP resource (`okf://persona-cross-links/<Type>/<id>.md`) and returns frontmatter + body via `resources/read`. It serves the identical Layer-2 projection; the deep model is not reachable through it at all.

```bash
# register with Claude Code
claude mcp add okf-persona -- node projects/shur/okf/serving/okf_mcp_server.mjs

# or smoke-test raw JSON-RPC
printf '%s\n' \
 '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}' \
 '{"jsonrpc":"2.0","id":2,"method":"resources/list"}' \
 | node projects/shur/okf/serving/okf_mcp_server.mjs
```

## The `resource:` URI scheme decision

This demo forced the open decision from the profile. **Decided 2026-07-13 with Jonny: the `resource:` target is a gated Cloudflare Worker URL** — real, on infrastructure we already run, and it makes the deny-without-auth contrast literal. The `totem://persona/<id>/<entity>` custom scheme remains the eventual production direction once a ShurIQ-agent resolver exists; an MCP `resource://` URI stays viable for agent-to-agent transport. The three are projections of the same boundary: a pointer that resolves only for the authorized.
