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.
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.
core/blog-comments.mjs owns records, validation, and
projections.core/policies.mjs is the sole policy source.core/actions.mjs owns local workflows and explicit
visitor/authority sync.bin/blog-comments.mjs owns files, identity-secret
permissions, arguments, and endpoint connections.web/main.mjs is the visitor-only browser adapter; no
browser workflow accepts an authority secret.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.
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.
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" 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.
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.