Blog Comments

Blog Comments is a CLI-first Lace experiment in immutable, approval-based publication. A visitor can publish a registration request and comment before approval. The configured blog authority later approves the exact registration request; the visitor’s original comment hash then appears in the published view. No promoted or rewritten comment is created.

The base frontend entry is //u//blog-comments//index.html; the packaged HTTP compatibility host serves //u//blog-comments/http//index.html.

Public pending boundary

OpenPending is public. The listener may store, expose, and transfer pending registration records and comment bodies to arbitrary peers before approval. Approval controls the normal Published comments projection, not access to the pending bytes. It does not retract records already copied, and the app defines no deletion or retention job.

The only supported post-policy pair is:

Publish-Mode: PreviouslyApproved
Submission-Mode: OpenPending

Registration and comment records are admitted only for a post with that authority-marked policy. The configured authority must mark blog/user and blog/post-policy; visitors mark their own blog/register and blog/comment records. Approval exact-links one validated registration request and grants the key that marked it the comment capability.

Multiple post-policy records for one post are an error: there is no replacement or conflict winner. Denial, revocation, post-policy succession, authority rotation, and delegated moderation have no record or transition semantics. Changing configuration does not create those semantics.

Boundaries

The authority job is manual: synchronize the public review set, approve one validated local request by exact hash, store the decision locally, then synchronize again. Reapproving an already approved visitor key fails.

Packaged host

The Deno host builds and serves the browser interface and Lace endpoint together on port 8817, with host records under .lace-data/blog-comments/host:

npm --prefix incubator/blog-comments run host

The printed HTTP URL opens the visitor page. Pass host options after --, for example --listen ws:0.0.0.0:9000/interlace or --store-path /srv/comments. The browser uses OPFS when available. A prominent warning identifies the weaker localStorage or temporary-memory fallback.

CLI workflow

Each --state directory contains one actor identity, public configuration, and filesystem Lace. By-secret values are stored in private/by-secret with mode 0600 and are never written to public config or accepted as argv values.

Create the authority and post policy:

BLOG=incubator/blog-comments/bin/blog-comments.mjs
node "$BLOG" identity init --state /tmp/blog-owner --role authority
AUTHORITY=$(node "$BLOG" identity show --state /tmp/blog-owner | node -e \
  "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>console.log(JSON.parse(s).by_value))")
node "$BLOG" config init --state /tmp/blog-owner \
  --group blog/demo --authority-key "$AUTHORITY" \
  --endpoint ws:127.0.0.1:8817/interlace
node "$BLOG" post-policy create --state /tmp/blog-owner \
  --post hello-lace --publish PreviouslyApproved --submission OpenPending
node "$BLOG" authority sync --state /tmp/blog-owner

Submit from a separate visitor:

node "$BLOG" identity init --state /tmp/blog-visitor --role visitor
node "$BLOG" config init --state /tmp/blog-visitor \
  --group blog/demo --authority-key "$AUTHORITY" \
  --endpoint ws:127.0.0.1:8817/interlace
node "$BLOG" visitor register --state /tmp/blog-visitor \
  --post hello-lace --username Alice
printf 'An immutable pending comment.\n' | node "$BLOG" visitor comment \
  --state /tmp/blog-visitor --post hello-lace --username Alice --body-stdin
node "$BLOG" visitor sync --state /tmp/blog-visitor --post hello-lace

Review and approve the exact request hash:

node "$BLOG" authority sync --state /tmp/blog-owner
node "$BLOG" authority pending --state /tmp/blog-owner --post hello-lace
node "$BLOG" authority approve --state /tmp/blog-owner \
  --request S.REGISTRATION.H3
node "$BLOG" authority sync --state /tmp/blog-owner

Use --body-file or --body-stdin for comment bodies. Authority commands may read the configured authority key from --secret-file or --secret-stdin.

Validation

npm --prefix incubator/blog-comments run check
npm --prefix incubator/blog-comments test
node scenario-tools/src/cli.mjs scenario-tools/blog-comments --format text
git diff --check

Tests cover the immutable approval transition, exact-link authority, and transfer of public pending records to an unauthenticated peer.