Forum is a public-read, registered-author-write Lace application. Its Deno CLI, browser, registrar, and waypoint host share the same TypeScript records, authority checks, projections, actions, and synchronization policy. The host has no Forum authority of its own. The browser keeps OPFS status in profile details and shows a main-page warning only when Lace falls back to localStorage or memory.
Every CLI workspace has one $FORUM_HOME/forum.json.
Create a key, initialize the workspace, and set a public profile:
export FORUM_HOME="$PWD/.alice"
deno task forum key create keys/alice.json
deno task forum config init \
--steward 'V.<forum-steward>.H3' \
--waypoint 'ws:127.0.0.1:8798/interlace' \
--key keys/alice.json
deno task forum profile set Alice
config init --key initially maps every task to that key.
The task map contains direct key-file paths for
registration.request, post.write,
registration.manage, moderation.manage, and
capability.manage. Edit those paths when duties use
different keys. There is no identity-name registry or key directory
scan.
Configured relative paths resolve below the workspace and must remain
inside it. Global --as KEY-FILE overrides the selected task
key for one invocation; absolute paths are accepted explicitly. Key
files contain only by_value and bySecret.
Loading re-derives the By value and, on Unix-like systems,
rejects group- or world-readable files. Creation uses a
0700 directory and exclusive 0600 file.
deno task forum config show
deno task forum key show keys/alice.json
deno task forum key list
deno task forum --as keys/staff.json profile set 'Forum staff'
The host operational key/store and registrar store are separate from task keys and the normal CLI Lace.
forum [--home PATH] [--as KEY-FILE] COMMAND
registration request [--message TEXT] [--sync]
registration status
registration pending [--format text|jsonl]
registration grant|deny REQUEST [--sync]
registration revoke SUBJECT [--sync]
capability grant|revoke SUBJECT registration.manage|moderation.manage [--sync]
moderation hide|restore TARGET [--reason-code CODE] [--sync]
post TITLE [BODY] [--sync]
reply TOPIC [BODY] [--sync]
topics | topic TOPIC | replies TOPIC
sync
post and reply read stdin when the body
argument is absent:
printf 'First post\n' | deno task forum post 'Hello'
printf 'A reply\n' | deno task forum reply 'S.<topic>.H3'
deno task forum sync
Mutations store locally first. If optional --sync fails,
the command reports the new hash and leaves the record local. Filesystem
stores are single-writer; do not concurrently open one
$FORUM_HOME/lace from separate commands.
An applicant publishes a request; an authorized manager grants or denies that exact request:
deno task forum registration request --message 'I would like to participate.' --sync
deno task forum registration pending --format jsonl
deno task forum registration grant 'S.<request>.H3' --sync
# or: deno task forum registration deny 'S.<request>.H3' --sync
deno task forum registration status
Status is missing, requested,
active, denied, or revoked. A
denial resolves only its linked request, does not revoke active
registration, and does not prevent a later request.
The root Forum Steward implicitly holds all administrative
capability. It alone grants the fixed, non-recursive
registration.manage and moderation.manage
capabilities:
deno task forum capability grant \
'V.<staff>.H3' registration.manage --sync
deno task forum capability grant \
'V.<moderator>.H3' moderation.manage --sync
Delegated registration and moderation decisions exact-link the current grant. Revoking that grant invalidates every delegated decision under it; granting the capability again does not revive old decisions. Root decisions need no grant link. Current capability, registration, and moderation state use greatest TAI, then greatest record hash. Hiding is projection, not deletion.
A root operator can provision a separate browser administrator without copying the root key or changing CLI task assignments:
deno task forum browser-key issue keys/gui-admin.json \
--origin https://forum.example \
--task registration.manage --task moderation.manage --sync
The printed import URL fragment contains a By-secret value. Keep it
out of logs, shell history, tickets, and chat. The browser removes the
fragment before fetching and may replace only its administrative task
assignments; its personal request/post key remains separate.
browser-key link reprints a link for an existing key. Links
are reusable key copies, not one-use tokens. Root capability revocation
is the authority transition. Root and waypoint-operational keys are
rejected.
The registrar selects the direct registration.manage
key, uses $FORUM_HOME/registrar/lace, and holds a workspace
registrar lock. It is not a host subtask.
deno task forum registrar once --auto-register
deno task forum registrar run --auto-register
deno task registrar once --register-with /opt/forum/bin/review-request
deno task registrar run --register-with /opt/forum/bin/review-request
--register-with requires an absolute executable path.
The hook receives the request hash as argv[1] and exact
canonical request bytes on stdin. Exit 0 grants and exit
1 denies; launch failures, signals, timeout, excessive
output, or any other exit leave the request pending.
Hook execution is at least once if the worker crashes before storing
its decision, so side effects must be idempotent by request hash. After
local storage, publication retries do not rerun the hook. Every decision
rechecks current registration.manage authority.
run uses bounded reconnect backoff and handles
SIGINT/SIGTERM.
deno task forum --home .host key create keys/operator-bootstrap.json
deno task forum --home .host config init \
--steward 'V.<forum-steward>.H3' \
--waypoint 'wss:forum.example/interlace' \
--key keys/operator-bootstrap.json
deno task forum --home .host host run
# deployment listener override:
deno task forum --home .host host run --listen ws:0.0.0.0:8798/interlace
The configured waypoint is the public connection address, not a
listener bind. Without --listen, the host binds to
ws:127.0.0.1:8798/interlace. Host identity and storage
remain operational boundaries and grant no Forum capability. The base
frontend entry is //u//forum//index.html; this
HTTP-compatible host serves
//u//forum/http//index.html.
From the Lace repository root:
(cd incubator/forum && deno task typecheck)
(cd incubator/forum && deno task test)
(cd incubator/forum && deno task test:e2e)
git diff --check -- incubator/forum