Releases: 100yenadmin/boardstate
Release list
Boardstate 1.8 — the operational, multi-agent workspace
The project-level release marker for the 1.8 generation — per-package tags (@boardstate/*@x.y.z) remain the granular record; this release exists so the repo front page reflects where the project actually is: schema / core / host / server @1.8.0, agent@0.5.0, lit@0.9.0, mcp@0.2.10, broker@0.3.4.
Since the 1.x extraction, two whole acts shipped:
M5 — The Operational Workspace
Boardstate became an MCP client: point it at OfficeCLI, Pipedream, Composio, or any MCP server and the board reads external tools as live data and runs them as operator-confirmed actions — agent-requests/human-grants, anti-rug-pull re-pend, pending-action parking, secrets node-side only.
Act 4 — The polished, multi-agent workspace
Per-tool auto-confirm + grant TTLs + async pending actions; multi-agent workspaces (server-bound actor scoping, provenance chips, per-agent budgets); template recipes (install = import, grants arrive requested); board-as-agent-memory; plus the polish/content wave (sparkline + chart detail, history previews, pomodoro + habit-tracker + Focus template, RTL audit, 5 locales at 100%).
Where it runs
- OpenClaw — adopted in-tree as "Workspaces" (openclaw/openclaw#101792, #104139)
- Hermes — boardstate-hermes-plugin (web dashboard + desktop app); bundling PRs open upstream (NousResearch/hermes-agent#66413)
Full story: CHANGELOG.md · every package ships to npm with Sigstore provenance.
@boardstate/server@1.8.0
Minor Changes
-
#74
ddc2710Thanks @100yenadmin! - Multi-agent workspaces (#59, SPEC §17.3): several agents sharing one board, distinguishable
and separately governed.- Per-agent grant scoping (schema + engine). A capability grant gains an optional
operator-setagents?: string[]— the ACTOR dimension of the AND-gate. Absent ⇒ all agents
(back-compat, zero migration); present ⇒ only those agent actors pass, at BOTH tool-set
assembly (the agent-tool adapter surfaces a scoped grant only to a bound, listed agent —
covering the directreadOnlypath) and invoke/read time (dashboard.action.invoke/
dashboard.connector.readfail-safe recheck). Operator-set ONLY (the approve verb);
tool_searchREQUEST /workspace.replace/ import can never write or widen it — any scope
drift on a still-granted grant re-pends the whole grant, and every re-pend (manifest drift,
replace/import, REQUEST, TTL expiry, revoke) strips it, exactly likeautoConfirm/expiresAt. - Actor authenticity (load-bearing). The acting agent is bound from the server-side
session/tool-registration identity (threadedRequestContext → RpcHandlerContext), NEVER a
request param. A parked mutation records the server-bound requester and the confirm-time
re-gate re-checks scope against IT. The WS transport threads no identity, so a scoped grant
FAILS CLOSED for an unauthenticated networked caller (capability_pending) — a client-claimed
actorcan never pass another agent's scope (wire-contract tested). - Per-agent rate budgets. The per-connector invoke limit gains an optional
perAgentInvokeRateMax: an agent's ceiling becomesmin(connector, per-agent). Unset ⇒
connector-only, byte-identical to prior behavior. - Provenance chips + filter (lit). On a board with ≥2 distinct agent authors, each widget
header shows a compact deterministically-coloured chip (short id, full actor on hover) and a
toolbar affordance filters/highlights one agent's widgets. The approvals widget renders each
grant's per-agent scope. Zero schema change; single-agent boards are unchanged. New i18n keys
added to the five complete locales.
- Per-agent grant scoping (schema + engine). A capability grant gains an optional
Patch Changes
@boardstate/server@1.7.0
Minor Changes
-
#70
39083ccThanks @100yenadmin! - Trust-tier trio on the §17 capability grant + §18 pending-action spine: per-tool
auto-confirm (#62), grant TTLs (#64), and async pending actions (#63).- Per-tool auto-confirm (#62, SPEC §17.2). A grant gains an optional operator-set
autoConfirm?: string[](⊆ its grantedtools). A non-readOnlytool in the set
executes DIRECTLY on invoke — no park — auditedauto-confirmedand broadcasting
dashboard.action.changed {status:"confirmed", autoConfirmed:true}, still rate-limited.
Operator-only (the approve verb); wiped on every re-pend (manifest drift,replace/import
surface mutation,tool_searchrequest, TTL expiry, revoke). - Grant TTLs (#64, SPEC §17). A grant gains an optional
expiresAt?: ISO-8601,
operator-set at approve time and required future-dated. After expiry the grant re-pends to
requested(tools drop,autoConfirmclears) — swept ON READ (fail-closed at every
reader incl. the confirm seam: park-then-expire-then-confirm is refused) plus a coarse host
timer. The clock is injectable. - Async pending actions (#63, SPEC §18.4). New
asyncActionsinstall option (default
false, blocking path byte-identical): an agent-invoked mutation returns a framed
{parked:true, id, expiresAt}immediately and the turn ends. Settlements are delivered via
a newonActionSettled(record, result)engine hook;@boardstate/agentadds an opt-in
createActionSettlementWakethat enqueues ONE follow-up turn per settlement (framed
untrusted, no recursive cascade). - Approvals widget (#62/#64). Per-tool auto-confirm toggles + a TTL field on capability
rows, a live "expires in" countdown, and renew/revoke on granted-grant management rows.
- Per-tool auto-confirm (#62, SPEC §17.2). A grant gains an optional operator-set
Patch Changes
- Updated dependencies [
39083cc]:- @boardstate/schema@1.7.0
- @boardstate/core@1.7.0
@boardstate/server@1.6.0
Patch Changes
- Updated dependencies [
eae965d]:- @boardstate/core@1.6.0
@boardstate/server@1.4.0
Minor Changes
-
#57
ed04514Thanks @100yenadmin! - feat(server): one-call M5 host wiring —installConnectorWorkspace(M5e)The connector broker's server-side pieces landed as separate installers with a load-bearing
ORDER; a Node host had to call four of them in the right sequence and thread three handles
intoregisterBoardstateRpc+ the agent tool set.installConnectorWorkspace
(@boardstate/server/node) encodes that assembly once: it installs the pending-action
engine FIRST (it registersdashboard.action.invoke), then the broker→AgentTool adapter,
then theboardstate_tool_searchbacking, and returns the two seams the caller still owns
explicitly —capabilityToolsHash(intoregisterBoardstateRpc) andtoolSearch(into
createDashboardTools). It consumes the broker through the existing narrow structural
interfaces (ActionBroker+AgentToolBroker), no@boardstate/brokerimport, so the
dependency arrow stays one-way. Additive: boards using no connector broker are unaffected.
@boardstate/server@1.3.0
Minor Changes
-
#55
52a3d3cThanks @100yenadmin! - feat(server): broker→AgentTool adapter +boardstate_tool_search(M5c-1 + M5c-2)Granted external MCP tools now reach the agent.
createBrokerAgentToolswraps each GRANTED
tool as anAgentTool(provider-safe name, untrusted-framed description,external: true);
readOnlytools execute directly through the broker while mutations route through the
server-enforced pending-action engine (park → await operator confirm), returning a
model-legible refusal on deny/timeout/expiry rather than throwing.installBrokerAgentTools
wires the adapter viahost.registerTool(grant/revoke picked up next turn).Adds the
boardstate_tool_searchcore tool (SEARCH a connector's full catalog, bounded and
schema-free; REQUEST tools by appending to the connector grant'srequestedset — never
grants, re-pends a granted grant per the merged partial-grant lifecycle) with the node-side
createBrokerToolSearchbacking.AgentToolgains an optionalexternalmarker. SPEC §18.1
and §18.2 document the agent surface and the request/approve loop.
Patch Changes
- Updated dependencies [
d2620ba]:- @boardstate/core@1.3.0
@boardstate/server@1.2.0
Minor Changes
-
#53
a0feba7Thanks @100yenadmin! - M5 trust layer (M5b-2 + M5b-3, epic #37): the grant lifecycle for external MCP tools
and the server-enforced pending-action engine — closes #40 and #41.Grant lifecycle + both-direction anti-rug-pull (SPEC §17.1, #40)
installBrokerActions(@boardstate/server/node) registers each configured connector's
discovered tools as arequestedtools-only grant (explicitmethods: []/streams: [],
atoolsid snapshot, and a subset-scopedtoolsHash), mirroringinstallConnector's
request-on-install. An already-grantedgrant survives a restart; real manifest drift is
caught at invoke time.- Server-side anti-rug-pull: on every granted-tool call the live manifest hash is compared
to the storedtoolsHash; a mismatch re-pends the grant torequestedBEFORE any call
succeeds. - Agent-side anti-rug-pull:
reconcileReplaceApprovalnow forces agrantedgrant back to
requestedon ANYtools/toolsHashmutation (not just status flips) — closing the
red-team hole where an agent could append a tool id to a granted grant through
workspace.replaceor import. - Partial grants:
dashboard.capability.approvegains an optionaltoolssubset; the
decision applies to the intersection with the requested set and the granted subset gets
its OWN hash (McpBroker.hashToolSubset, injected ascapabilityToolsHash). - Approvals console: capability rows surface their requested tool ids for per-tool selection
(approve-all = one click); the core transform + lit renderer + strings render it.
Pending-action engine (SPEC §18, #41)
- In-memory pending-action registry.
dashboard.action.invokeAND-gates a call (granted at
invoke time + connector configured + hash unchanged): areadOnlygranted tool executes
directly; a mutation parks as aPendingActionRecordand returns{ pending: true, id, expiresAt }.dashboard.action.confirm/dashboard.action.denyare operator-only
(OPERATOR_ONLY_METHODS) — a networked client can directly execute onlyreadOnlytools. - TTL expiry (~5 min), single-shot terminal states (a replay of a terminal id errors),
server-side invoke rate limiting (prompt-gate discipline), an audit entry per invoke +
decision, and lifecycle broadcasts ondashboard.action.changed. confirmAndExecute(id)is exposed as the awaitable an agent-mediated call (M5c-1) blocks
on: it resolves with the tool result on confirm and rejects on deny/expiry.
The engine consumes the broker through the narrow structural
ActionBrokerinterface —
@boardstate/brokernever enters@boardstate/server(no dependency cycle); the real
McpBrokerfits it structurally. SPEC §17.1/§18 normative text filled where the schema
train (#39) left implementation-pending markers.
Patch Changes
c895241- Security: thedashboard_workspace_replaceagent tool now passes the structural
replace gate (reconcileReplaceApproval), so an agent can no longer self-grant a
capability by writingstatus: "granted"intocapabilitiesRegistry. Only
dashboard.capability.approve(operator-only) grants. The RPC replace path was
already gated; this closes the agent-tool path.- Updated dependencies [
b05c7cd,a0feba7]:- @boardstate/schema@1.2.0
- @boardstate/core@1.2.0
@boardstate/server@1.1.0
Patch Changes
- Updated dependencies [
364898d]:- @boardstate/core@1.1.0
@boardstate/server@1.0.0
Major Changes
-
af1df09- The capability broker (SPEC §17, M4b) — approval-gated data-source grants. Extends
the approval model from agent-authored widget CODE to DATA sources, per ADR
docs/decisions/0001-capability-broker.md.@boardstate/schema: a top-levelcapabilitiesRegistry(optional on input;
always present after validation) — grants keyed by connector name, each carrying
its allowlist-validated method/stream snapshot andrequested/granted/revoked
status. Import re-pends every grant and stripsgrantedBy/grantedAt(an imported
board carries no active capability).@boardstate/core:reconcileReplaceApprovalnow also forces any grant
self-elevated tograntedback torequestedin the write lock, so a
replace/import can never grant a capability.normalizeWorkspacecarries the
registry through the client read model.@boardstate/server(BREAKING):installConnectornow REQUIRESnameand
takesstore+description. On install a connector registers its grant
requested; its reads answercapability_pendingand its streams broadcast
nothing until an operator approves. New operator-only RPC
dashboard.capability.approve(inOPERATOR_ONLY_METHODS; never in the agent tool
catalog) grants/revokes; revocation stops all its bindings immediately. A connector
changing its declared shape re-requests. Omittingstorekeeps the pre-§17
behavior (serve immediately). The reference sidecar declares + auto-approves its
grant.
Migration: an existing
installConnector({ reads, streams })call becomes
installConnector({ name, store, reads, streams })and the operator (or the host at
boot, for a single-operator localhost) approves the connector's grant.
Patch Changes
- Updated dependencies [
af1df09]:- @boardstate/schema@1.0.0
- @boardstate/core@1.0.0
@boardstate/server@0.5.1
Patch Changes
51a8ef9- Security: the WS transport now refuses operator-only methods
(dashboard.widget.approve) over the wire by default. The networked transport
threads no operator identity, so an operator ACTION arriving over the wire has
no authenticated operator behind it — yetattachWsTransportpreviously
forwarded EVERY method (scope is metadata, never a dispatch gate), so opening a
read-only networked viewer silently also exposed the widget-approval gate to any
client that passedverifyClient(a confused-deputy footgun). Approve is now
blocked before dispatch unless the host opts in withallowOperatorMethods: true(for when it authenticates the operator itself inverifyClient).
Composing/driving the board over the wire is unchanged. Found while framing the
M4b capability broker (approve-unreachable-by-networked-requesters is its
prerequisite).