Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .crumb
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
"generated": {
"children": [],
"children_root": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"compiled_at": "2026-10-30T02:45:42Z",
"compiled_at": "2026-10-31T11:06:08Z",
"compiler": "crumb-compile/1",
"digest": "sha256:3608cd20218bfba79866fec8aec75e5d75483f9708acc1c8c5765fb803d8fcc4",
"digest": "sha256:afd6980ce178bd547afeec7e8ae8dda3b9be098ceaf14ea6a38f3e19ca533290",
"evidence_files": 63,
"evidence_root": "sha256:490153d15f32b2c3a501ec7777f3acbd024889e03f4062026743b10306bd20de",
"files": 80,
"generated_at_commit": "90bfb601224738481e363b8da7f0f65b2b6dd79a",
"source_tree": "sha256:f98eb4b192f71039b6feb39a31d453c863ddc543c81cec110ac0d81494c2fb03"
"files": 84,
"generated_at_commit": "6b38a9d1264de1f71543fcc8b1346059719e8d30",
"source_tree": "sha256:142fb1c9c8dd2e9ac9df9bb8f1ee4b9213a667f6f1b08e51528892eacde97fe7"
}
},
"invariants": [
Expand Down
14 changes: 14 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Dependabot: monthly version updates for the pinned GitHub Actions and the Cargo lockfile.
# Pull requests only; nothing merges itself. Security advisories are handled by GitHub
# Dependabot security updates on the repository settings.
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
- package-ecosystem: cargo
directory: /
schedule:
interval: monthly
versioning-strategy: lockfile-only
37 changes: 37 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# CI: build and test with the committed Cargo.lock (--locked refuses any silent dependency
# drift) on a GitHub-hosted runner, with pinned actions and read-only token permissions.
# A second job writes an SPDX SBOM of the tree so auditors can diff what a commit contains.
name: CI
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@b725eda525362e7cf34af9a7243cac1e3f01a7ec # stable
- name: Toolchain record
run: rustc --version && cargo --version
- name: Build
run: cargo build --locked --all-targets
- name: Test
run: cargo test --locked
sbom:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
persist-credentials: false
- uses: anchore/sbom-action@66cbf4bc1f1c0d2edc94016e65bc221b6bb0ad6c # v0.24.3
with:
path: .
format: spdx-json
artifact-name: sbom-${{ github.sha }}.spdx.json
108 changes: 108 additions & 0 deletions AUDIT_SCOPE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Audit scope

Written for an outside, independent security audit. Revision described:
`c0e11da06565a812c7384982a2a14d8352325993` on `main`, 2026-10-31. Everything below is taken from the repository's own files at
that revision; items marked NOT_RUN were not executed while writing this document.

## What this repository is

The source of the INTERPLANE website. A Cargo workspace with one crate, `crates/site-builder`
(version 0.2.0, `publish = false`): `facts.rs` (488 lines) reads the protocol repository through
`gh api`, `page.rs` (397) holds the copy and the Maud markup, `routes.rs` (67) names the six
routes (Overview, Quick Start, Concepts, Adapter, Conformance, Status), `discovery.rs` (168)
writes the JSON-LD block, `robots.txt`, `sitemap.xml` and `llms.txt` and checks them, and
`main.rs` (362) has the `facts`, `build` and `verify` commands and tests. `public/` holds
`style.css` and `hero.webp`. `scripts/sync-to-hub.sh` (71 lines) is the deploy job. `dist/` and
`facts.json` are generated and ignored. Licence AGPL-3.0-or-later.

## What to review, in priority order

1. `crates/site-builder/src/page.rs`: every place a fact string is placed into markup. Maud
escapes `(expr)` by default. The one `PreEscaped` (`page.rs:74`) inserts
`discovery::script`: JSON-LD built with `serde_json`, with `&`, `<`, `>`, U+2028 and U+2029
written as `\u` escapes, inside one `<script type="application/ld+json">`. Check that escape
set, and attribute values and link targets built from facts (for example URLs that could
become `javascript:` or `http://`).
2. `verify_html` and `verify` in `main.rs`, and `verify` and `json_block` in `discovery.rs`: the
rule checks that gate publication (exactly one inert JSON-LD block, no executable script, head
metadata equal to the generated route head). Check each AGENTS.md rule is enforced and cannot
be bypassed by unusual casing or encoding.
3. `crates/site-builder/src/facts.rs`: `gh` and `gh_text` call `gh api` with arguments built from
the constant `PROTOCOL_REPO` and values read from earlier responses (commit sha, file paths);
Markdown parsers `status_counts`, `conformance_row`, `headline`, `stages`,
`public_description`; status selection by `SPARK_STATUS_CONTEXT`. `PROTOCOL_REPO` is
`aien-dev/interplane-mv`, the name AGENTS.md uses; it was `aien-dev/interplane` on `main`,
which only worked through GitHub's rename redirect, and this change asks for the real name.
4. `scripts/sync-to-hub.sh`: skips while the machine's quiet flag is held, clones or fast-forwards
`main`, refuses a dirty checkout, builds with `cargo build -q --locked --release -p site-builder`
(`--locked` added by this change), falls back to the last good `facts.json` when `facts` fails, refuses on `verify`
failure, compares a `cksum` with the last published one, then `rsync -a --delete` to the web
host over SSH (excluding `.well-known`). `REPO`, `HUB`, `WEBDIR`, `LOGDIR` come from the
environment.
5. `copy_dir` and `build` in `main.rs`: copying `public/` into the output.

## Trust boundaries

- Untrusted input: the protocol repository's README and status data as returned by the GitHub
API. Anyone who can merge there influences the page text.
- Trusted: the `gh` login used by `facts` (AGENTS.md: it never writes a token), the deploy host's
SSH access to the web server, and `main` of this repository (merges publish within an hour).
- Visitor side: the output is static HTML and CSS.

## Threat model summary

- Assets: integrity of the public site; honesty of the figures it shows; the deploy SSH key.
- Attackers considered: hostile or mistaken text in the protocol repository; an unreviewed change
on `main`.
- Defended: Maud escaping, `verify` rules before publication, refusal of dirty checkouts,
last-good-facts fallback.
- Not defended / explicitly out of scope: the web server configuration, TLS for interplane.io and
the deploy host are outside the repository; `rsync --delete` mirrors whatever `build` produced.

## Build from source at a pin

Needs a stable Rust toolchain (version not pinned). Dependencies `maud` 0.26, `serde` 1,
`serde_json` 1; `Cargo.lock` committed (18 packages).

```sh
cargo build --release -p site-builder
```

`site-builder facts` needs `gh`, logged in, and network access to GitHub.

## Run every test

NOT_RUN while writing this document. From AGENTS.md:

```sh
cargo test -p site-builder # renders a sample page and runs the verify rules
target/release/site-builder facts # needs gh login and network; writes facts.json
target/release/site-builder build dist
target/release/site-builder verify dist
```

Test attributes at this revision: 6 in `facts.rs`, 8 in `main.rs`. Expected: `test result: ok`.
`scripts/sync-to-hub.sh`: do not run (AGENTS.md); it needs the deploy host and its SSH access.
NOT_RUN.

## Known limitations and NOT_RUN

- Hosted CI (`.github/workflows/ci.yml`, added with this document) runs `cargo build --locked
--all-targets`, `cargo test --locked` and an SBOM job. It does not run `facts` or `verify`
against live data.
- On `main` the deploy build did not pass `--locked` and `PROTOCOL_REPO` named the old
repository; both are corrected by this change (items 3 and 4 above).
- Hosting, TLS and web server configuration are not in this repository.

## Dependencies and provenance

- `Cargo.lock` committed; crates from crates.io.
- Build-time tools for the deploy: `git`, `cargo`, `gh`, `rsync`, `ssh`, `cksum`; versions not
pinned.
- AGENTS.md: no Node build, no package manager besides Cargo; no GitHub Pages workflow or `CNAME`.

## Evidence

No signed receipts are stored in this repository; `evidence/` holds the `ONBOARDING-L642` and
`discoverability-issue7` evidence sets. Every figure on the page names the protocol commit it was
read at (AGENTS.md). The deploy job keeps its log and last facts outside the repository.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# interplane.io

Source of the website for [INTERPLANE](https://github.com/aien-dev/interplane), the open
Source of the website for [INTERPLANE](https://github.com/aien-dev/interplane-mv), the open
interoperability protocol between AI models and agent runtimes.

Part of Sovereign Intelligence (SI). Aienix is retired.
Expand Down Expand Up @@ -35,7 +35,7 @@ page names the commit it was read at and links to it. The editorial copy lives i
## Build

```
cargo build --release -p site-builder
cargo build --locked --release -p site-builder
target/release/site-builder facts # needs `gh` logged in; writes facts.json
target/release/site-builder build dist # renders all six routes, copies public/, facts.json
target/release/site-builder verify dist
Expand Down
58 changes: 58 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Security policy

## Reporting a vulnerability

Report privately. Do not open a public issue, pull request or discussion about it.

Report vulnerabilities privately through the repository's Security tab, "Report a vulnerability",
at https://github.com/aien-dev/interplane.io/security/advisories/new.

Include the commit or release you tested, the component (path), steps to reproduce, and what an
attacker gains. If the report involves a secret, say where it was exposed and do not send the
secret itself. Do not post proof-of-concept payloads publicly.

## Response targets

This project has one maintainer; the targets below are best effort and stated honestly.

- Acknowledgement: within 3 working days.
- Triage and severity: within 7 days of acknowledgement.
- Fix or mitigation for confirmed issues: aim for 30 days for high and critical, 90 days
otherwise, with a status update at least every 14 days until closed.
- Disclosure: coordinated. An advisory is published with credit (unless you ask otherwise)
once the fix is on the default branch. Default embargo 90 days, negotiable.

## Scope

This repository builds the static INTERPLANE website. One Rust program, `crates/site-builder`,
reads the protocol repository's public record on GitHub, writes the facts to `facts.json`, renders
`dist/index.html` with Maud templates, and refuses a page that breaks the site rules.
`scripts/sync-to-hub.sh` is the hourly deploy job.

In scope:

- Text from the protocol repository (README tables, descriptions, commit status contexts) that
reaches the page unescaped, injects markup or script, or produces a figure the protocol
repository does not record.
- A page that passes `site-builder verify` while breaking a rule AGENTS.md lists: static HTML and
CSS only, no scripts, no outside fonts or trackers, no plain `http://` links, browser requests to
interplane.io only, the Spark verdict shown exactly as read.
- `scripts/sync-to-hub.sh` publishing a dirty checkout, a page that failed `verify`, or anything
outside the build output.
- Tokens or SSH material written to tracked files, `facts.json` or logs.

Out of scope:

- The protocol itself, which lives in its own repository; GitHub, the `gh` CLI, the web server
that hosts the site, and the host operating system.

## Supported versions

Only the default branch `main`, which is what the hourly job publishes. Reports against older commits are welcome but fixes land on the default branch only.

## Status

The live site is built from `main` by the hourly job (AGENTS.md). Hosted CI
(`.github/workflows/ci.yml`) builds and tests the crate with `--locked` on pull requests and
pushes to `main`. No certification, no bug bounty. See AUDIT_SCOPE.md for what to review and how
to build and test it.
5 changes: 3 additions & 2 deletions crates/site-builder/src/facts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ use std::process::Command;

use serde::{Deserialize, Serialize};

/// The protocol repository. GitHub follows the rename, so this name keeps working.
pub const PROTOCOL_REPO: &str = "aien-dev/interplane";
/// The protocol repository under its current name. The old name `aien-dev/interplane` still
/// redirects, but a redirect stops working if that name is ever reused, so ask for the real one.
pub const PROTOCOL_REPO: &str = "aien-dev/interplane-mv";

/// The commit status context under which the Spark judge posts its verdict.
pub const SPARK_STATUS_CONTEXT: &str = "AIEN Verification (Spark)";
Expand Down
2 changes: 1 addition & 1 deletion scripts/sync-to-hub.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ git merge -q --ff-only origin/main
HEAD=$(git rev-parse --short=12 HEAD)

export CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$REPO/target}"
cargo build -q --release -p site-builder
cargo build -q --locked --release -p site-builder
BIN="$CARGO_TARGET_DIR/release/site-builder"

if "$BIN" facts "$LOGDIR/facts.json" >>"$LOG" 2>&1; then
Expand Down
Loading