From 1f1dde41bf35462c28ea355fdbe9a75523063863 Mon Sep 17 00:00:00 2001 From: David Abutbul Date: Wed, 15 Apr 2026 20:59:03 +0000 Subject: [PATCH] docs(wiki): expand hermes attestation claim narratives and archive draft --- ...04-15-hermes-attestation-guardian-draft.md | 111 -------- wiki/GENERATION.md | 2 +- wiki/INDEX.md | 4 +- ...rmes-attestation-guardian-draft-history.md | 54 ++++ wiki/modules/hermes-attestation-guardian.md | 261 ++++++++++++++++-- 5 files changed, 300 insertions(+), 132 deletions(-) delete mode 100644 docs/plans/2026-04-15-hermes-attestation-guardian-draft.md create mode 100644 wiki/modules/hermes-attestation-guardian-draft-history.md diff --git a/docs/plans/2026-04-15-hermes-attestation-guardian-draft.md b/docs/plans/2026-04-15-hermes-attestation-guardian-draft.md deleted file mode 100644 index 6353adc..0000000 --- a/docs/plans/2026-04-15-hermes-attestation-guardian-draft.md +++ /dev/null @@ -1,111 +0,0 @@ -# Hermes Attestation Guardian (Historical Draft Record) - -Date: 2026-04-15 -Owner: draft prepared for delegated implementation -Status: Implemented in repository (v0.0.1); this draft is historical context only - -## 1) Proposed skill identity - -Name: hermes-attestation-guardian -Why this name: -- Explicitly Hermes-scoped (no ambiguity with OpenClaw runtime skills) -- Keeps ClawSec "guardian" naming family -- Clear security function (attestation + guard) - -Tagline: -"Continuously attest Hermes runtime security posture and surface drift before it becomes incident." - -## 2) Product positioning (Hermes-first) - -Primary audience: -- Operators running Hermes CLI/Gateway infra (Telegram/Matrix/Discord, local + remote hosts) - -Non-goal: -- OpenClaw hook runtime protection -- Generic multi-agent platform abstraction beyond Hermes - -Core value pillars: -1. Trust posture visibility: one signed snapshot of security state -2. Drift detection: compare baseline vs current and emit high-signal deltas -3. Operator-safe controls: no destructive remediation by default, explicit approvals required - -## 3) Security outcomes - -The skill should attest and diff at least: -- Enabled toolsets and risky toggles -- Messaging/gateway active state -- Signed feed verification state (where configured) -- Integrity-sensitive file hashes (operator-selected policy) -- Runtime version + dependency fingerprint summary - -Priority alerts: -- unsigned mode or bypass flags enabled in production profile -- critical verification regression (signature/checksum failure) -- protected config/runtime file drift -- change in trust anchors (key fingerprint mismatch) - -## 4) Hermes alignment rules (must-have) - -Naming and metadata: -- skill.json name must be hermes-attestation-guardian -- platform field must be hermes -- triggers must include explicit Hermes language (avoid generic "security check" only) - -Paths and side effects: -- default output under ~/.hermes/security/attestations/ -- no writes to ~/.openclaw paths -- no destructive actions (quarantine/delete/restore) in MVP - -Runtime/UX: -- fail closed for attestation verification errors -- operator-facing messages must separate: INFO / WARNING / CRITICAL -- remediation must be recommendation-only unless user explicitly opts in - -## 5) ClawSec pipeline/distribution requirements - -Based on existing repo automation, this skill must satisfy: -- skills//skill.json contains required fields: name, version, description, author, license, sbom.files -- skills//SKILL.md includes YAML frontmatter with matching version -- version parity: skill.json version == SKILL.md frontmatter version -- CHANGELOG.md must contain heading exactly: - ## [] - YYYY-MM-DD -- SBOM required file entries must exist in repo -- README.md recommended for site rendering - -Release mechanics this skill should be compatible with: -- scripts/release-skill.sh version bump + URL rewrites -- .github/workflows/skill-release.yml parity/release-note checks -- utils/validate_skill.py local validation - -## 6) Skeleton contents created - -skills/hermes-attestation-guardian/ -- skill.json -- SKILL.md -- README.md -- CHANGELOG.md -- scripts/generate_attestation.mjs -- scripts/verify_attestation.mjs -- scripts/setup_attestation_cron.mjs -- lib/diff.mjs -- test/attestation_schema.test.mjs -- test/attestation_diff.test.mjs - -## 7) Delegate implementation brief - -Delegate goal: -Prepare a production-ready v0.0.1 of hermes-attestation-guardian from this skeleton while keeping Hermes-only positioning and ClawSec release compatibility. - -Required implementation scope: -1. Implement deterministic attestation schema + generator CLI -2. Implement verifier CLI (schema + signature/checksum hooks, fail-closed semantics) -3. Implement baseline diff engine with stable severity mapping -4. Implement cron setup helper for Hermes environments (no OpenClaw assumptions) -5. Add/expand tests for schema, diff correctness, and failure behavior -6. Keep docs and metadata aligned with actual behavior (no aspirational claims) - -Acceptance checks before return: -- python utils/validate_skill.py skills/hermes-attestation-guardian -- Version parity and changelog heading satisfy skill-release policy -- Node tests in skill directory pass -- Tool/runtime side effects are explicitly documented in SKILL.md diff --git a/wiki/GENERATION.md b/wiki/GENERATION.md index 61c827b..3c2424d 100644 --- a/wiki/GENERATION.md +++ b/wiki/GENERATION.md @@ -15,7 +15,7 @@ - Updated index and cross-links to use `wiki/` as the documentation source of truth. - Added a dedicated module page for `clawsec-scanner` and linked it from `wiki/INDEX.md`. - Future updates should preserve existing headings and append `Update Notes` sections when making deltas. -- 2026-04-15: Added `wiki/modules/hermes-attestation-guardian.md` documenting PR claims in human-friendly claim→wiring format. +- 2026-04-15: Expanded `wiki/modules/hermes-attestation-guardian.md` into full narrative claim breakdowns (people-speak + wiring + verification + scenario) and moved draft-plan context into `wiki/modules/hermes-attestation-guardian-draft-history.md`. ## Source References - README.md diff --git a/wiki/INDEX.md b/wiki/INDEX.md index 2aa1710..aa93daf 100644 --- a/wiki/INDEX.md +++ b/wiki/INDEX.md @@ -31,6 +31,7 @@ - [ClawSec Suite Core](modules/clawsec-suite.md) - [ClawSec Scanner](modules/clawsec-scanner.md) - [Hermes Attestation Guardian](modules/hermes-attestation-guardian.md) +- [Hermes Attestation Guardian Draft History (Archived)](modules/hermes-attestation-guardian-draft-history.md) - [NanoClaw Integration](modules/nanoclaw-integration.md) - [Automation and Release Pipelines](modules/automation-release.md) - [Local Validation and Packaging Tools](modules/local-tooling.md) @@ -42,7 +43,7 @@ - [Generation Metadata](GENERATION.md) ## Update Notes -- 2026-04-15: Added Hermes Attestation Guardian module page with human-friendly claim-to-code/test mappings from PR description. +- 2026-04-15: Expanded Hermes Attestation Guardian module page into full narrative, claim-by-claim operator guidance (no claim tables), and added archived draft-history module page. - 2026-03-10: Added ClawSec Scanner module documentation and linked it under Modules. - 2026-02-26: Added Operations pages and updated navigation guidance after migrating root docs into wiki pages. @@ -58,4 +59,5 @@ - skills/hermes-attestation-guardian/skill.json - wiki/modules/clawsec-scanner.md - wiki/modules/hermes-attestation-guardian.md +- wiki/modules/hermes-attestation-guardian-draft-history.md - .github/workflows/ci.yml diff --git a/wiki/modules/hermes-attestation-guardian-draft-history.md b/wiki/modules/hermes-attestation-guardian-draft-history.md new file mode 100644 index 0000000..7b43f3f --- /dev/null +++ b/wiki/modules/hermes-attestation-guardian-draft-history.md @@ -0,0 +1,54 @@ +# Module History: Hermes Attestation Guardian Draft (Archived) + +## Purpose +This page preserves the original planning draft that led to `hermes-attestation-guardian` v0.0.1. +It is historical context, not current behavior contract. + +## Status +- Draft date: 2026-04-15 +- Current status: implemented in repository as `skills/hermes-attestation-guardian` v0.0.1 +- Source of truth for live behavior: skill code, tests, and `wiki/modules/hermes-attestation-guardian.md` + +## What the draft got right +- Hermes-only positioning (not OpenClaw hook runtime scope). +- Fail-closed verification as a core requirement. +- Deterministic attestation and digest binding requirements. +- Baseline-vs-current drift detection with severity ranking. +- Safe cron automation expectations (explicit apply, non-destructive defaults). + +## Original design intent (summarized) +1) Identity and scope +- Name should clearly indicate Hermes scope and guardian role. +- Metadata should make platform targeting explicit. + +2) Security outcomes +- Snapshot posture and integrity-sensitive inputs. +- Detect risky toggles, verification regressions, and trust/file drift. +- Prioritize high-signal alerts for operators. + +3) Alignment rules +- Keep side effects under Hermes paths. +- Avoid destructive remediation in MVP. +- Keep operator-facing criticality clear. + +4) Packaging/release compatibility +- Match ClawSec skill metadata and changelog requirements. +- Ensure local validation and test gates pass before release. + +5) Delegate implementation scope +- Build generator, verifier, diff logic, cron helper, and tests. +- Keep docs aligned to implemented behavior. + +## What changed from draft to implementation +- Implementation hardened path-scope checks (including symlink-aware escape defense). +- Verifier baseline trust was made explicit and fail-closed before diffing. +- Cron managed-marker parser hardened to fail closed on malformed marker structure. +- Wiki documentation now maps each PR claim to wiring and tests with human-readable operator guidance. + +## Where to look now +- Live module documentation: + - `wiki/modules/hermes-attestation-guardian.md` +- Live skill implementation: + - `skills/hermes-attestation-guardian/` +- Validation tests: + - `skills/hermes-attestation-guardian/test/` diff --git a/wiki/modules/hermes-attestation-guardian.md b/wiki/modules/hermes-attestation-guardian.md index fd045f3..9b810c9 100644 --- a/wiki/modules/hermes-attestation-guardian.md +++ b/wiki/modules/hermes-attestation-guardian.md @@ -2,38 +2,262 @@ ## Responsibilities - Produce a deterministic Hermes runtime security snapshot (attestation). -- Verify attestation integrity in fail-closed mode before trust decisions. +- Verify attestation integrity in fail-closed mode before any trust decision. - Compare trusted baseline vs current posture and classify drift severity. - Provide a safe, Hermes-scoped automation path for periodic attestation checks. -## Claims from PR description (human-friendly) +## PR Claims: Full Human-Friendly Breakdown -| Claim | In people-speak | Where it is wired (code/config) | How we verify it | -| --- | --- | --- | --- | -| Adds deterministic attestation generation with canonicalized payload digesting. | If nothing changed in Hermes, the attestation fingerprint should stay the same. No noisy diffs from JSON ordering. | `skills/hermes-attestation-guardian/scripts/generate_attestation.mjs`, `skills/hermes-attestation-guardian/lib/attestation.mjs` (`stableStringify`, canonical digest helpers), `skills/hermes-attestation-guardian/skill.json` | `node skills/hermes-attestation-guardian/test/attestation_schema.test.mjs` checks deterministic output and digest/schema expectations. | -| Enforces fail-closed verification for schema, digest, optional expected checksum, and detached signatures. | Verification must stop with an error when integrity checks fail; never “best effort pass.” | `skills/hermes-attestation-guardian/scripts/verify_attestation.mjs`, `skills/hermes-attestation-guardian/lib/attestation.mjs`, operator notes in `skills/hermes-attestation-guardian/skill.json` and `SKILL.md` | `node skills/hermes-attestation-guardian/test/attestation_cli.test.mjs` covers tamper/error paths and non-zero exits. | -| Adds baseline authenticity and drift-severity classification for risky toggles, feed verification regressions, trust anchor drift, and watched file drift. | Baseline diff is trusted only when baseline authenticity is proven, then drift is ranked by severity so operators can act fast. | Baseline trust gates in `scripts/verify_attestation.mjs`; drift engine in `lib/diff.mjs`; docs in `README.md`/`SKILL.md` | `node skills/hermes-attestation-guardian/test/attestation_cli.test.mjs` (baseline trust/tamper) and `node skills/hermes-attestation-guardian/test/attestation_diff.test.mjs` (severity mapping). | -| Adds Hermes-only cron setup helper with managed marker block and print-only default. | Cron setup is opt-in and safe by default: it prints planned changes unless `--apply` is explicit. | `skills/hermes-attestation-guardian/scripts/setup_attestation_cron.mjs`, `skills/hermes-attestation-guardian/SKILL.md` | `node skills/hermes-attestation-guardian/test/setup_attestation_cron.test.mjs` validates print-only behavior and managed-block logic. | -| Includes output-scope/path guardrails for attestation artifacts and policy parsing safeguards. | Output writes are constrained to Hermes attestation scope, including symlink-aware escape defense. | `skills/hermes-attestation-guardian/lib/attestation.mjs` (`resolveHermesScopedOutputPath`), `scripts/generate_attestation.mjs`, `scripts/setup_attestation_cron.mjs` | `node skills/hermes-attestation-guardian/test/attestation_cli.test.mjs` includes out-of-scope and symlink-escape rejection checks. | -| Cron managed-block parser fails closed on malformed markers. | If cron markers are broken, updater refuses to rewrite instead of risking accidental deletion. | `skills/hermes-attestation-guardian/scripts/setup_attestation_cron.mjs` (`removeManagedBlock`) | `node skills/hermes-attestation-guardian/test/setup_attestation_cron.test.mjs` covers dangling start, unmatched end, and nested marker failures. | +This section rewrites each PR claim as an operator-facing explanation, then ties it to exact code and tests. + +### Claim 1: Adds deterministic attestation generation with canonicalized payload digesting. + +Absolutely — in people-speak: + +We create a security snapshot of Hermes in a way that is reproducible, then fingerprint it in a stable way so tampering or real drift is obvious. + +What this means in practice: +1) Attestation generation +- Think of it as a report card for Hermes security posture at a moment in time. +- It records posture fields, trust anchors, watched-file hashes, and metadata. + +2) Deterministic output +- Same state should produce the same attestation content. +- No noise from object insertion order or formatting randomness. + +3) Canonicalization before hashing +- Payload is normalized into one canonical JSON representation. +- This removes ambiguity from normal JSON variations. + +4) Digest binding +- SHA-256 is computed over canonical payload content. +- Any meaningful change to payload changes digest. +- Any post-generation tampering causes verification mismatch. + +Where it is wired: +- `skills/hermes-attestation-guardian/scripts/generate_attestation.mjs` +- `skills/hermes-attestation-guardian/lib/attestation.mjs` + - `stableSortObject` + - `stableStringify` + - `sha256Hex` + - `buildAttestation` + - `computeCanonicalDigest` + - `validateDigestBinding` + +How to verify: +- `node skills/hermes-attestation-guardian/test/attestation_schema.test.mjs` + - proves same-input determinism and canonical digest consistency. +- `node skills/hermes-attestation-guardian/test/attestation_cli.test.mjs` + - proves post-generation tamper causes fail-closed digest mismatch. + +Quick scenario: +- Same state: run generator twice with unchanged inputs -> same digest. +- Tampered file: flip a posture value in JSON -> verifier fails on canonical digest mismatch. + +--- + +### Claim 2: Enforces fail-closed verification for schema, digest, optional expected checksum, and detached signatures. + +In people-speak: + +Verification is not “best effort.” If a trust check fails, verification fails. No soft pass. + +What is fail-closed here: +1) Schema must be valid. +2) Canonical digest must match payload. +3) If `--expected-sha256` is supplied, file bytes must exactly match. +4) If detached signature verification is requested, signature + public key must both be present and valid. + +Where it is wired: +- `skills/hermes-attestation-guardian/scripts/verify_attestation.mjs` + - schema checks + - digest checks + - expected checksum check + - detached signature verification + - non-zero exit on critical failure +- `skills/hermes-attestation-guardian/lib/attestation.mjs` + - `validateAttestationSchema` + - `validateDigestBinding` + +How to verify: +- `node skills/hermes-attestation-guardian/test/attestation_schema.test.mjs` + - proves schema rejection and digest algorithm validation behavior. +- `node skills/hermes-attestation-guardian/test/attestation_cli.test.mjs` + - proves tamper path exits non-zero (fail closed). + +Quick scenario: +- CI pins expected SHA and requires detached signature. +- Artifact is modified or signed incorrectly -> verification exits non-zero and blocks pipeline. + +--- + +### Claim 3: Adds baseline authenticity and drift-severity classification for risky toggles, feed verification regressions, trust anchor drift, and watched file drift. + +In people-speak: + +You only compare against a baseline after proving the baseline itself is authentic. Then differences are ranked by severity so operators can respond quickly. + +What this gives operators: +1) Authenticated baseline gate +- Baseline must be trusted (pinned digest and/or detached signature trust path). +- Untrusted baseline is rejected before diffing. + +2) Severity-ranked drift findings +- Critical/high/medium/low/info mapping instead of flat alerts. +- High-signal categories include: + - risky toggle enablement, + - feed verification regressions, + - trust anchor hash drift, + - watched file hash drift. + +3) Policy-driven failure threshold +- Verification can fail when findings meet/exceed configured severity threshold. + +Where it is wired: +- Baseline trust and diff orchestration: + - `skills/hermes-attestation-guardian/scripts/verify_attestation.mjs` +- Drift engine and severity mapping: + - `skills/hermes-attestation-guardian/lib/diff.mjs` + - `diffAttestations` + - `highestSeverity` + - `severityAtOrAbove` + +How to verify: +- `node skills/hermes-attestation-guardian/test/attestation_cli.test.mjs` + - proves untrusted baseline rejection and digest-pinned baseline handling. +- `node skills/hermes-attestation-guardian/test/attestation_diff.test.mjs` + - proves classification for key drift types and highest-severity behavior. + +Quick scenario: +- Yesterday’s baseline is pinned and trusted. +- Today `allow_unsigned_mode` flips on and trust anchor hash changes. +- Diff emits critical findings and verifier can fail run by severity policy. + +--- + +### Claim 4: Adds Hermes-only cron setup helper with managed marker block and print-only default. + +In people-speak: + +You get a scheduler helper that is safe by default: it shows planned cron changes first, and only writes when you explicitly ask. + +What “safe by default” means: +1) Hermes-only framing in UX and docs. +2) Managed marker block for clean replacement of only this module’s cron section. +3) Print-only default; write path requires explicit `--apply`. + +Where it is wired: +- `skills/hermes-attestation-guardian/scripts/setup_attestation_cron.mjs` + - managed markers + - print-only defaults + - apply path +- Supporting scope/docs: + - `skills/hermes-attestation-guardian/SKILL.md` + - `skills/hermes-attestation-guardian/skill.json` + +How to verify: +- `node skills/hermes-attestation-guardian/test/setup_attestation_cron.test.mjs` + - proves Hermes-only messaging and managed-block behavior. + - proves default mode is preview-oriented and apply path is explicit. + +Quick scenario: +- Operator runs cron helper without flags -> sees proposed block only. +- Operator reviews, then reruns with `--apply` -> only managed block is updated. + +--- + +### Claim 5: Includes output-scope/path guardrails for attestation artifacts and policy parsing safeguards. + +In people-speak: + +Artifact writes are fenced into Hermes attestation scope, including symlink-escape defenses, and policy parsing is normalized/defensive so bad input fails cleanly. + +What this protects against: +1) Out-of-scope writes +- Output path must remain under `HERMES_HOME/security/attestations`. + +2) Symlink escapes +- Path resolution checks nearest existing ancestors and symlink behavior to prevent “write outside root” tricks. + +3) Safer policy parsing +- Missing/invalid structure gets normalized defaults where appropriate. +- Malformed JSON fails closed. +- List fields are trimmed, deduplicated, and sorted. + +Where it is wired: +- Guardrails: + - `skills/hermes-attestation-guardian/lib/attestation.mjs` + - `resolveHermesScopedOutputPath` +- Call sites: + - `skills/hermes-attestation-guardian/scripts/generate_attestation.mjs` + - `skills/hermes-attestation-guardian/scripts/setup_attestation_cron.mjs` +- Policy parsing: + - `skills/hermes-attestation-guardian/lib/attestation.mjs` + - `parseAttestationPolicy` + +How to verify: +- `node skills/hermes-attestation-guardian/test/attestation_cli.test.mjs` + - proves out-of-scope and symlink-escape output rejection. +- `node skills/hermes-attestation-guardian/test/setup_attestation_cron.test.mjs` + - proves cron helper also rejects out-of-scope output target. + +Quick scenario: +- Operator accidentally sets `--output /tmp/current.json`. +- Tool exits with critical path-scope error instead of writing outside Hermes scope. + +--- + +### Claim 6: Cron managed-block parser fails closed on malformed markers. + +In people-speak: + +If cron markers are malformed (dangling start/end or nested blocks), updater refuses to rewrite crontab to avoid accidental deletion or corruption. + +What this means operationally: +1) Marker structure is treated as integrity-sensitive input. +2) Malformed structure throws and aborts apply path. +3) No crontab write occurs after malformed marker detection. + +Where it is wired: +- `skills/hermes-attestation-guardian/scripts/setup_attestation_cron.mjs` + - `removeManagedBlock` + - marker parsing and malformed-marker throw paths + +How to verify: +- `node skills/hermes-attestation-guardian/test/setup_attestation_cron.test.mjs` + - proves fail-closed behavior for: + - dangling start marker, + - unmatched end marker, + - nested markers, + - and verifies no write on malformed input. + +Quick scenario: +- Existing crontab has managed start marker with no end marker. +- Running `--apply` aborts with malformed-marker error and leaves crontab unchanged. ## Key Files - `skills/hermes-attestation-guardian/skill.json`: metadata, platform scope, operator review notes, SBOM. - `skills/hermes-attestation-guardian/SKILL.md`: operator playbook, CLI usage, fail-closed policy. - `skills/hermes-attestation-guardian/README.md`: quickstart and practical behavior notes. -- `skills/hermes-attestation-guardian/lib/attestation.mjs`: canonicalization, digest binding, schema checks, scoped output resolution. +- `skills/hermes-attestation-guardian/lib/attestation.mjs`: canonicalization, digest binding, schema checks, scoped output resolution, policy parsing. - `skills/hermes-attestation-guardian/lib/diff.mjs`: baseline drift comparison and severity classification. - `skills/hermes-attestation-guardian/scripts/generate_attestation.mjs`: deterministic attestation generation CLI. - `skills/hermes-attestation-guardian/scripts/verify_attestation.mjs`: fail-closed verifier and baseline trust enforcement. - `skills/hermes-attestation-guardian/scripts/setup_attestation_cron.mjs`: cron managed-block helper. ## Public Interfaces -| Interface | Consumer | Behavior | -| --- | --- | --- | -| `generate_attestation.mjs` CLI | Operators/automation | Creates canonicalized attestation JSON and optional checksum artifact. | -| `verify_attestation.mjs` CLI | Operators/automation/cron | Enforces schema/digest/signature checks and optional trusted baseline drift checks. | -| `setup_attestation_cron.mjs` CLI | Operators | Prints or applies managed cron block for scheduled generate+verify runs. | -| Diff output contract | Operators/CI | Emits severity-ranked drift findings for security triage. | +- `generate_attestation.mjs` CLI + - Consumer: operators/automation + - Behavior: creates canonicalized attestation JSON and optional checksum artifact. +- `verify_attestation.mjs` CLI + - Consumer: operators/automation/cron + - Behavior: enforces schema/digest/signature checks and optional trusted-baseline drift checks. +- `setup_attestation_cron.mjs` CLI + - Consumer: operators + - Behavior: prints or applies managed cron block for scheduled generate+verify runs. +- Diff output contract + - Consumer: operators/CI + - Behavior: emits severity-ranked drift findings for security triage. ## Validation Commands ```bash @@ -45,7 +269,7 @@ node skills/hermes-attestation-guardian/test/setup_attestation_cron.test.mjs ``` ## Update Notes -- 2026-04-15: Added module page for `hermes-attestation-guardian` and documented PR-claim-to-code/test traceability in human-friendly terms. +- 2026-04-15: Replaced table-style PR claim mapping with full narrative claim breakdowns (people-speak, wiring, verification, and concrete scenarios per claim). ## Source References - skills/hermes-attestation-guardian/skill.json @@ -61,4 +285,3 @@ node skills/hermes-attestation-guardian/test/setup_attestation_cron.test.mjs - skills/hermes-attestation-guardian/test/attestation_diff.test.mjs - skills/hermes-attestation-guardian/test/attestation_cli.test.mjs - skills/hermes-attestation-guardian/test/setup_attestation_cron.test.mjs -- docs/plans/2026-04-15-hermes-attestation-guardian-draft.md