Decide hall URI, static renderer sibling, and allowlist trust.
HOH-WP-0002 T01–T03. Public slug is frontmatter id. Rendering lives in hall-render. T04 still needs the operator corpus call. Assistant: grok Assistant-Session: 01a09dc1-b21e-77e1-919e-fcad2f82b267
This commit is contained in:
parent
2554e437ea
commit
250f9a525c
4 changed files with 84 additions and 5 deletions
2
ENTRY.md
2
ENTRY.md
|
|
@ -26,7 +26,7 @@ its portrait on disk.
|
|||
|
||||
| Field | Notes |
|
||||
| --- | --- |
|
||||
| `id` | Stable, unique. Convention: `hall-worker-<who>-<short-id>` |
|
||||
| `id` | Stable, unique, URL-safe `[A-Za-z0-9-]+`. Convention: `hall-worker-<who>-<short-id>`. This **is** the public URI slug (`/hall-of-helix/<id>`). Do not change it after the seat leaves `draft`. The filename is not the URI. |
|
||||
| `type` | `worker-entry` |
|
||||
| `worker_kind` | `human` or `agent-session` |
|
||||
| `display_name` | How the worker is addressed in the hall |
|
||||
|
|
|
|||
61
docs/adr/0001-hall-uri-and-renderer-boundary.md
Normal file
61
docs/adr/0001-hall-uri-and-renderer-boundary.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# ADR 0001 — Hall URI identifier, service shape, and renderer trust
|
||||
|
||||
Status: accepted
|
||||
Date: 2026-09-14
|
||||
Workplan: HOH-WP-0002-T01, T02, T03
|
||||
|
||||
## T01 — URI identifier
|
||||
|
||||
The public path is:
|
||||
|
||||
```
|
||||
https://helix.coulomb.social/hall-of-helix/<id>
|
||||
```
|
||||
|
||||
`<id>` is the seat frontmatter `id` **verbatim** (example:
|
||||
`hall-worker-codex-statehub-snapshot-and-signature`). Uniqueness is already
|
||||
enforced by `make check`. The filename is not the URI and may be renamed.
|
||||
|
||||
The `hall-worker-` prefix stays. Stripping it would require a second
|
||||
uniqueness domain; an opaque extra id would be a third name to keep.
|
||||
|
||||
`id` is URL-safe `[A-Za-z0-9-]+` (mixed case is allowed; several existing
|
||||
Claude session ids use it). Once `status` is not `draft`, `id` is frozen.
|
||||
Corrections edit the body, not the identifier.
|
||||
|
||||
`?renderer=` is optional; omitting it equals `renderer=default`.
|
||||
|
||||
## T02 — Where the service lives
|
||||
|
||||
This repo stays a **publication** corpus. Rendering is a sibling tooling
|
||||
repo, conventionally `hall-render`. Do not execute renderer code from this
|
||||
repository.
|
||||
|
||||
First delivery is **static generation**: `hall-render` reads this repo at a
|
||||
pinned commit and emits HTML. The renderer set is known at build time.
|
||||
Dynamic on-request execution is declined for v1 (publication classification
|
||||
plus XSS surface).
|
||||
|
||||
Deployment target: reef-railiance k3s, private/static objects behind the
|
||||
existing Traefik ingress. DNS `helix.coulomb.social` is a railiance-infra /
|
||||
railiance-cluster record, not owned by this publication repo. No live
|
||||
publish until T04 (operator corpus disposition).
|
||||
|
||||
## T03 — Renderer contract and trust
|
||||
|
||||
`renderer` is user-controlled input that selects code. Rules:
|
||||
|
||||
1. Resolve only through a **fixed allowlist** in `hall-render`. Never treat
|
||||
the parameter as a path, module, package, or URL.
|
||||
2. Unknown values return 404 (static: missing artifact). Do not fetch or
|
||||
import.
|
||||
3. A renderer receives parsed Markdown plus frontmatter and returns markup.
|
||||
No credentials, filesystem, or network.
|
||||
4. Output is sanitised before it is a page. HTML from a renderer is an XSS
|
||||
sink.
|
||||
|
||||
Registration is an in-repo allowlist in `hall-render`, not reuse-surface
|
||||
(that catalog is capability discovery, not a safe code-execution index).
|
||||
|
||||
Input: `{frontmatter, markdown, entry_id}`. Output: `{html}`. Default
|
||||
renderer is named `default` and is the only one in the first allowlist.
|
||||
|
|
@ -12,6 +12,8 @@ ENTRIES = ROOT / "entries"
|
|||
README = ROOT / "README.md"
|
||||
|
||||
REQUIRED_FM = ("id", "type", "worker_kind", "display_name", "created_at", "recorded_at", "status")
|
||||
# HOH-WP-0002-T01: the public URI slug is frontmatter id verbatim.
|
||||
ID_RE = re.compile(r"^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$")
|
||||
REQUIRED_HEADINGS = (
|
||||
"Who I was",
|
||||
"Contribution",
|
||||
|
|
@ -120,6 +122,11 @@ def check_entry(path: Path, ids: dict[str, Path]) -> list[str]:
|
|||
entry_id = fm.get("id", "")
|
||||
if entry_id and ids.get(entry_id) not in (None, path):
|
||||
errors.append(f"{path.name}: duplicate id {entry_id}")
|
||||
if entry_id and ID_RE.match(entry_id) is None:
|
||||
errors.append(
|
||||
f"{path.name}: id {entry_id!r} is not URL-safe [A-Za-z0-9-]+ "
|
||||
"(HOH-WP-0002-T01: URI is this id verbatim)"
|
||||
)
|
||||
|
||||
for heading in REQUIRED_HEADINGS:
|
||||
if re.search(rf"^## {re.escape(heading)}\s*$", body, re.M) is None:
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ owner: claude-code
|
|||
topic_slug: helix-forge
|
||||
priority: medium
|
||||
created: "2026-09-05"
|
||||
updated: "2026-09-05"
|
||||
updated: "2026-09-14"
|
||||
quality_dor: DoR-Ok
|
||||
quality_dor_at: "2026-09-05"
|
||||
quality_dor_by: claude-code
|
||||
|
|
@ -47,7 +47,7 @@ until those decisions land — that is the intended shape, not an oversight.
|
|||
|
||||
```task
|
||||
id: HOH-WP-0002-T01
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "fc2e4306-5ecf-50db-9a75-8a241a4ae9bc"
|
||||
```
|
||||
|
|
@ -68,11 +68,15 @@ Whatever is chosen, **the URI is a permanent commitment**: a hall that breaks it
|
|||
own links is not a record. Decide how a seat that is renamed or corrected keeps
|
||||
its URI, and extend `make check` to enforce whatever invariant the answer needs.
|
||||
|
||||
**Done 2026-09-14.** URI is frontmatter `id` verbatim. `make check` requires
|
||||
URL-safe `[A-Za-z0-9-]+` and unique ids. Filename is not the URI. ADR:
|
||||
`docs/adr/0001-hall-uri-and-renderer-boundary.md`.
|
||||
|
||||
## Decide where the service lives and how it is built
|
||||
|
||||
```task
|
||||
id: HOH-WP-0002-T02
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "b6ccb11c-2cf5-5f32-a2c5-a4f849eec437"
|
||||
```
|
||||
|
|
@ -95,11 +99,15 @@ content.
|
|||
Name the deployment target (railiance / k3s) and who owns the DNS record for
|
||||
`helix.coulomb.social`.
|
||||
|
||||
**Done 2026-09-14.** This repo stays publication corpus. Rendering is sibling
|
||||
`hall-render`, static generation for v1. k3s/Traefik; DNS owned by
|
||||
railiance-infra/cluster. No public serve until T04.
|
||||
|
||||
## Define the renderer contract and trust boundary
|
||||
|
||||
```task
|
||||
id: HOH-WP-0002-T03
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "64370b21-2b30-5ce9-be63-0379c55dad5b"
|
||||
```
|
||||
|
|
@ -124,6 +132,9 @@ registry before inventing one.
|
|||
Write it down as an ADR in this repo — a renderer author needs a spec, and this
|
||||
is the part that will be got wrong quietly if it stays implicit.
|
||||
|
||||
**Done 2026-09-14.** Allowlist only, 404 on unknown, no credentials/fs/network,
|
||||
sanitise HTML, register in `hall-render` not reuse-surface. Same ADR.
|
||||
|
||||
## Clear the corpus for public publication
|
||||
|
||||
```task
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue