docs(readme): overhaul the README for the program, and relicense to MIT
Some checks failed
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Meridian Harness / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Meridian Harness / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Meridian Harness / Publish rolling release (push) Has been cancelled
Meridian Harness / Publish tagged release (push) Has been cancelled
control plane / chart (push) Has been cancelled
control plane / test (push) Has been cancelled
control plane / browser-e2e (push) Has been cancelled
control plane / Build control plane image (linux/amd64) (push) Has been cancelled
control plane / Build control plane image (linux/arm64) (push) Has been cancelled
control plane / Publish signed control plane image (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Server Cross-Compile (push) Has been cancelled
CI / Server Cross-Compile-1 (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled

The README still read as a consumer-facing chat product with Block
attribution, while the repo has become a two-data-plane relay backbone with
a written Design Law, profiled throughput ceilings, and a 10-week
decentralized-relay program. Rewrite it to say that, evidence-graded
throughout: every figure carries measured/estimate/target and its profile,
per AGENTS.md.

- Lead with the two-relays-in-one-binary model (signed events for humans and
  agents; opaque header-routed frames for machines) and the refusal that
  makes the machine path possible.
- Publish the ceilings table with profiles and the commands that reproduce
  it, plus the narrowed broker claim (bus, policy, audit role) and the
  hub-and-leaf seam ratified in DIAGRAM.md Part III.
- Summarise Design Law, the named refusals, the tier contracts, and the
  quality gates; point program state at TASKS.md and Beads rather than
  restating it.
- Link every in-repo target as an absolute Gitea URL on main, so links
  resolve wherever the README is rendered.

Relicense Apache-2.0 -> MIT with STELLAR as the attribution: LICENSE,
workspace and meridian-persona manifests, cargo-deny clarification for
meridian-desktop, ARCHITECTURE.md, CONTRIBUTING.md, VISION.md, the ACP
crate README, and the Helm chart (version bump to 0.1.10 so chart-testing
sees the metadata change, maintainer updated). Third-party attributions in
harness-logos/CREDITS.md are upstream terms and stay untouched.

Signed-off-by: Joshua Belke <joshua@innovationhub-act.org>
This commit is contained in:
Josh Belke 2026-08-05 14:47:03 -04:00
commit 6c2fcedd10
11 changed files with 431 additions and 382 deletions

View file

@ -94,8 +94,9 @@
{"_type":"issue","id":"meridian-rs6","title":"Decide legacy-avatar migration semantics for retired starter personas","description":"4 tests in desktop/src-tauri/src/migration_avatar_tests.rs fail after the starter team was renamed to the first-party Codebase agents.\n\nCause: LEGACY_BUILTIN_AVATARS is correctly keyed by the ids records were STORED under (builtin:fizz/honey/bumble). refresh_builtin_agent_avatars_in_file resolves that legacy id against the CURRENT builtins via built_in_persona_avatar_url, which now returns None because those ids moved to RETIRED_PERSONAS. So old records keep their bee avatar.\n\nThat may be correct: retired personas are deactivated and renamed '(retired)', so keeping their original look is defensible. The alternative is adding a successor mapping (fizz-\u003ecodebase-design, honey-\u003ecodebase-planning, bumble-\u003ecodebase-research) so retired records adopt the new artwork.\n\nFailing: current_builtin_agent_avatars_do_not_match_legacy_hashes, refresh_builtin_agent_avatars_updates_seeded_values_and_preserves_customizations, refresh_builtin_agent_avatars_updates_uploaded_media_urls, refresh_builtin_agent_avatars_updates_versions_without_stored_definitions.\n\nNeeds a product decision before the tests are rewritten - do not force them green.","status":"closed","priority":1,"issue_type":"task","owner":"joshua@innovationhub-act.org","created_at":"2026-07-31T13:09:24Z","created_by":"Joshua Belke","updated_at":"2026-08-05T12:29:14Z","closed_at":"2026-08-05T12:29:14Z","close_reason":"Settled by meridian-yvm: retired personas keep their original bee art. Option (b) (repoint through RETIRED_PERSONA_REPLACEMENTS) would have given the retired Fizz card the Codebase Design face — two cards, one avatar — and was rejected. Deleting the dead migration removes new behaviour rather than adding it, so no product decision was needed.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"meridian-4qs","title":"Decide on renaming bee-themed persona ids (builtin:fizz etc)","description":"Fizz/Honey/Bumble are bee-themed names across ~500 sites. Persona ids like builtin:fizz are PERSISTED in user data and referenced in Rust migration code (desktop/src-tauri/src/templates/storage.rs, migration/materialize.rs). Renaming is a data migration requiring a compat path, not a cosmetic swap.","status":"closed","priority":1,"issue_type":"task","owner":"joshua@innovationhub-act.org","created_at":"2026-07-31T07:36:55Z","created_by":"Joshua Belke","updated_at":"2026-08-05T11:58:27Z","closed_at":"2026-07-31T13:09:41Z","close_reason":"Renamed to first-party Codebase agents: builtin:fizz-\u003ebuiltin:codebase-design, builtin:honey-\u003ebuiltin:codebase-planning, builtin:bumble-\u003ebuiltin:codebase-research. Old ids added to RETIRED_PERSONAS with their ORIGINAL prompts verbatim, so the existing retirement path distinguishes untouched from user-customized personas. Prompts rewritten first-party (no mascot voice/wordplay); bee-themed name_pools replaced.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"meridian-hwe","title":"Replace starter-team bee character artwork (Fizz/Honey/Bumble)","description":"desktop/public/onboarding/starter-team/{fizz,honey,bumble}.png are illustrated 3D bee mascots from the Buzz brand. Needs commissioned illustration - not auto-generatable. Shown on the welcome kickoff stage and community onboarding.","status":"closed","priority":1,"issue_type":"task","owner":"joshua@innovationhub-act.org","created_at":"2026-07-31T07:36:55Z","created_by":"Joshua Belke","updated_at":"2026-08-05T11:58:27Z","closed_at":"2026-07-31T13:09:41Z","close_reason":"Replaced with first-party Codebase agent avatars: brand bracket on per-agent tile colours (research #6d5df6, planning #3b82f6, design #06b6d4), baked by desktop/scripts/app-icon/generate-agent-avatars.mjs. Bee PNGs deleted.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"meridian-66v","title":"Desktop: app-data migration re-copies legacy .window-state.json every launch","description":"The pre-rebrand app-data migration (xyz.block.codebasechat.app.dev.main -\u003e zone.ilab.office.r2d2.meridian.app.dev.main) copies .window-state.json forward on EVERY launch, not just the first. If the saved geometry came from a display arrangement no longer attached (observed: x=5551 y=-246), the window opens off-screen: process runs, no error logged, no window appears, and AXWindows reports 0. run.sh cmd_desktop now resets an unreachable origin as a workaround (commit c5f4d8db4), but the migration itself should be one-shot, or should not carry window geometry forward at all. Reproduce: plant off-screen coords in the legacy dir and launch.","status":"open","priority":2,"issue_type":"bug","owner":"joshua@innovationhub-act.org","created_at":"2026-08-05T17:35:00Z","created_by":"Joshua Belke","updated_at":"2026-08-05T17:35:00Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"meridian-9ao","title":"Guard DIAGRAM.md Part I against pipeline drift","description":"The LLM Council review of DIAGRAM.md Parts I-III (Sr. Full Stack Developer seat) raised a standing risk: Part I's write/read path diagrams are traced to line-level facts (req.rs:90/:209, handlers/event.rs:580) and nothing fails when a refactor makes them false. check-kinds guards vocabulary because vocabulary drift is silent; pipeline-description drift is silent the same way, and a confidently wrong diagram costs more than no diagram.\n\nTwo options, either acceptable:\n 1. A doc-drift guard in the just check gate that asserts the cited symbols still exist and the described ordering still holds.\n 2. Rewrite the citations to name functions and invariants rather than line numbers, accepting weaker precision for durability.\n\nNot a doc edit - it is a CI change, which is why the council deferred it rather than applying it inline.","status":"open","priority":2,"issue_type":"task","owner":"joshua@innovationhub-act.org","created_at":"2026-08-05T12:51:35Z","created_by":"Joshua Belke","updated_at":"2026-08-05T12:51:35Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"meridian-70h","title":"run.sh: verify desktop (tauri dev) launch end-to-end","description":"run.sh desktop --attach was validated up to the build boundary: sidecar binaries built, desktop frontend built, and instance-env.sh confirmed to honour the exported MERIDIAN_VITE_PORT/HMR_PORT/RELAY_URL (devUrl + beforeDevCommand both carry the override). The tauri dev GUI launch itself was not run in this session. Launch it once and confirm the window connects to the run.sh-allocated relay port.","status":"open","priority":2,"issue_type":"task","owner":"joshua@innovationhub-act.org","created_at":"2026-08-05T12:30:11Z","created_by":"Joshua Belke","updated_at":"2026-08-05T12:30:11Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"meridian-70h","title":"run.sh: verify desktop (tauri dev) launch end-to-end","description":"Desktop launch verified up to the window boundary only. CONFIRMED WORKING: Tauri crate compiles (meridian-desktop v0.5.2), sidecars build, vite serves on the run.sh-allocated port 29775, instance-env.sh honours exported MERIDIAN_VITE_PORT/HMR_PORT/RELAY_URL (devUrl + beforeDevCommand both carry the override), app process starts and completes app-data migration with no error. NOT VERIFIED: the app window itself. Agent-spawned background shells are detached (sess=0, tty=??) and the process never registers with LaunchServices, so WindowServer grants no window and AXWindows reports 0 — an artefact of how the agent launches processes, not of run.sh or the app. Needs a human to run './run.sh desktop --attach' from a normal terminal and confirm the window renders and connects to ws://localhost:3002.","status":"open","priority":2,"issue_type":"task","owner":"joshua@innovationhub-act.org","created_at":"2026-08-05T12:30:11Z","created_by":"Joshua Belke","updated_at":"2026-08-05T17:35:13Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"meridian-yeb","title":"run.sh: cover port allocator + override writers with a contract test","description":"scripts/test-*-contract.sh style test for run.sh: sticky saved ports, lockstep pairs (PG/DATABASE_URL, REDIS_HOST_PORT/REDIS_URL, MINIO/S3_ENDPOINT, relay/BIND_ADDR/RELAY_URL/ADMIN_HOST), managed-block preservation of hand-written .env.local content, and !override tags in the generated compose file. Should run without Docker like compose-check does.","status":"open","priority":2,"issue_type":"task","owner":"joshua@innovationhub-act.org","created_at":"2026-08-05T12:26:24Z","created_by":"Joshua Belke","updated_at":"2026-08-05T12:26:24Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"meridian-ham","title":"Flaky: relay_admission concurrent_429_extends_the_window_for_parked_waiters","description":"Fails intermittently under full-suite parallel load in desktop/src-tauri --lib:\n\n assertion `left == right` failed: waiter must respect the extension armed mid-sleep (1s + 4s)\n left: 300.001s\n right: 5s\n\n300.001s is the parked waiter's outer cap, so the extension armed mid-sleep was not observed — the measured sleep ran to the cap instead of the 5s window. Consistent with a starved tokio test clock when ~1900 tests run concurrently, not with a logic defect.\n\nEvidence: passes 3/3 in isolation; full --lib suite passes 2/2 at 1920/1920 immediately after a failing run; the preceding full `just ci` was green with the same code path untouched.\n\nFix direction: make the test drive time deterministically (tokio time pause/advance) rather than measuring wall-clock against a real sleep.","acceptance_criteria":"The test either uses a paused clock or is otherwise made deterministic; 20 consecutive full --lib runs pass.","status":"open","priority":2,"issue_type":"bug","owner":"joshua@innovationhub-act.org","created_at":"2026-08-05T12:15:56Z","created_by":"Joshua Belke","updated_at":"2026-08-05T12:15:56Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"meridian-5fu","title":"Decide whether the sprig crate keeps its Sprout-era name","description":"`sprig` is the all-in-one ACP/agent/dev-MCP harness. The name is a Sprout diminutive and is the last brand-lineage artifact left after the Meridian rebrand.\n\nUnlike the other sprout leftovers it is not stored state, so renaming is safe from a migration standpoint — but it names a shipped binary, a Docker image, and .github/workflows/sprig.yml, which makes it outward-facing rather than a sweep.\n\nFootprint: crates/sprig/, Cargo.toml workspace member, .github/workflows/sprig.yml, .github/workflows/{docker,helm-chart}.yml, crates/AGENTS.md, crates/meridian-acp/AGENTS.md, .settings/features/feature-agent-distribution.md, AGENTS.md.\n\nOptions: (a) keep — it reads as a component name, not a brand; (b) rename to meridian-harness and update the workflow + image name in one change.","acceptance_criteria":"A recorded decision; if renamed, the crate, binary, workflow, image name and docs move together and just ci stays green.","status":"closed","priority":2,"issue_type":"task","owner":"joshua@innovationhub-act.org","created_at":"2026-08-05T03:31:39Z","created_by":"Joshua Belke","updated_at":"2026-08-05T11:58:27Z","closed_at":"2026-08-05T03:43:46Z","close_reason":"Renamed. sprig -\u003e meridian-harness: crate, binary, scripts/build-meridian-harness.sh, .github/workflows/meridian-harness.yml, meridian-harness-v* tags and the meridian-harness-latest rolling release. The multicall personalities it dispatches on (meridian-acp, meridian-agent, meridian-dev-mcp) were already renamed, so only the wrapper moved. cargo check --workspace --all-targets clean; Cargo.lock regenerated.","dependency_count":0,"dependent_count":0,"comment_count":0}

View file

@ -14,7 +14,7 @@ EVENT, REQ, REST, media, git, search, workflow, or pub/sub handling. Unknown
hosts fail closed, and NIP-98/API-token stamps must agree with the host-derived
community rather than overriding it.
Meridian is a Rust monorepo, licensed Apache 2.0 under Block, Inc.
Meridian is a Rust monorepo, licensed MIT and built by STELLAR.
This document is the **component reference** — what each crate is, what it
does, what it explicitly does not do. For the system view built on top of it —

View file

@ -515,11 +515,11 @@ If an HTTP endpoint is still necessary:
## License and CLA
Meridian is licensed under the **Apache License, Version 2.0**. See
[LICENSE](LICENSE) for the full text.
Meridian is licensed under the **MIT License**. See [LICENSE](LICENSE) for the
full text.
By submitting a pull request, you agree that your contribution is licensed
under the Apache 2.0 license and that you have the right to submit it.
under the MIT license and that you have the right to submit it.
If your employer has rights to intellectual property you create, you may need
their sign-off. When in doubt, check with your legal team.

View file

@ -36,7 +36,7 @@ resolver = "2"
version = "0.1.0"
edition = "2021"
rust-version = "1.88.0"
license = "Apache-2.0"
license = "MIT"
repository = "https://git.office.ilab.zone/RAID/R2D2-MERIDIAN"
[workspace.dependencies]

214
LICENSE
View file

@ -1,201 +1,21 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
MIT License
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
Copyright (c) 2026 STELLAR
1. Definitions.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Copyright 2026 Block, Inc.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

582
README.md
View file

@ -1,269 +1,497 @@
<h1 align="center">Meridian</h1>
<p align="center">
<strong>A workspace where humans and agents build together, on a relay you own.</strong>
<strong>One binary. Two data planes.</strong><br>
Signed, stored, indexed events for humans and agents — opaque, ephemeral, header-routed frames for machines.
</p>
<p align="center">
<a href="VISION.md">Vision</a> ·
<a href="VISION_SOVEREIGN.md">Sovereign</a> ·
<a href="VISION_PROJECTS.md">Forge</a> ·
<a href="VISION_AGENT.md">Agents</a> ·
<a href="ARCHITECTURE.md">Architecture</a> ·
<a href="LICENSE">Apache 2.0</a>
<a href="#quick-start">Quick start</a> ·
<a href="https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/ARCHITECTURE.md">Architecture</a> ·
<a href="https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/DIAGRAM.md">System map</a> ·
<a href="https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/TASKS.md">Program plan</a> ·
<a href="https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/AGENTS.md">Design Law</a> ·
<a href="https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/CONTRIBUTING.md">Contributing</a> ·
<a href="https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/LICENSE">MIT</a>
</p>
<p align="center">
<img src="docs/assets/screenshots/channel-thread.png" alt="A Meridian project channel where people and an agent coordinate on a release plan" width="100%">
</p>
<p align="center">
<sub><em>People and agents building together in the same room.</em></sub>
<img src="https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/raw/branch/main/docs/assets/screenshots/channel-thread.png" alt="A Meridian project channel where people and an agent coordinate on a release plan" width="100%">
</p>
---
## What is this, really?
## What this is
Meridian is a self-hostable workspace where humans and AI agents share the same rooms.
Meridian is a self-hosted relay that carries two kinds of traffic that share a
process and almost nothing else:
A Meridian **community** is the workspace a user reaches by URL. In the single-relay
setup that ships today, the relay URL selects exactly one community. A hosted
operator can serve many communities behind many domains or subdomains, but the
client-facing rule stays the same: the URL is authoritative for the workspace,
and all tenant-observable state under that URL is community-local.
- **The human and agent path** — every message, reaction, review, workflow step
and git object is a signed [Nostr NIP-01](https://github.com/nostr-protocol/nips/blob/master/01.md)
event in one Postgres log. Verified, ordered, stored, indexed, audited.
- **The machine path** — telemetry, tracks and sensor frames move as opaque
bytes behind a fixed-width routing header. The relay reads the header, routes
on it, and **never parses the payload**.
It's a Nostr relay: every message, reaction, workflow step, review approval, and git event is a signed event in one log. Same shape, same identity model, same audit trail, whether the author is a person or a process.
Together they make Meridian a modular replacement for the **bus, policy and
audit role** of a central MQTT broker, plus a decentralization story a broker
cannot tell: authorship that survives the hop.
In practice it feels like a team workspace. Under the hood it's an event log with taste and a suspicious number of Rust crates.
Yes, it's another AI-adjacent developer tool. We're sorry. The difference is what agents can actually *do* once they're inside: open repos, send patches, review code, run workflows, edit canvases, orchestrate other agents, drop into voice huddles, create channels, and pull in whoever needs to see it. The same affordances as a human teammate, the same audit trail, a different keypair.
A **community** is the tenant boundary and the URL is authoritative for it. One
deployment can host many communities; nothing tenant-observable crosses between
them, and the fence is bound from the request host before any handler sees data.
---
## Stuff you do in Meridian
## Two rules that govern every number in this repository
- **Ask the project a question and get an answer with receipts.** Agents search six months of history and post the threads, not vibes.
- **Let an agent triage a bug without giving it the keys to the kingdom.** Agents have their own keys, their own channel memberships, and their own audit trail. Scoped by identity, not by permission flags — the same way you'd scope a teammate.
- **Turn a feature branch into a room** where patches, CI, review, and the merge decision live together — so the channel becomes the record of why the code exists.
- **Search the conversation, the patch, the workflow run, and the approval in one place** — because they're all the same kind of event.
- **Let an agent run the workspace, not just talk in it.** Channels, canvases, workflows, huddles — agents have the same surface area as humans, with their own keys and their own audit trail.
Both are binding contract in [AGENTS.md](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/AGENTS.md), not editorial preference.
1. **No throughput figure without its profile** — traffic class, auth profile,
whether the payload is *parsed*, whether it is *stored*. One relay has two
ceilings roughly two orders of magnitude apart. Quoting the good one without
its qualifier is how you acquire an obligation the binary cannot meet.
2. **Nothing is resolved until deployed to a live relay and re-probed.** Green
CI is not evidence that an enforcement path runs in production. A deployed
image predating the enforcement code makes a feature flag a silent no-op.
Every claim below carries one of these labels, and they are not interchangeable:
| Label | Means |
| --- | --- |
| **measured** | a committed benchmark in this repo produced this number |
| **estimate** | derived from measured parts, not measured end to end |
| **target** | a goal behind a gate, not a result |
| **designed** | specified, no code in tree |
| **refused** | deliberately not built, with a written reason |
---
## A look inside
## The mental model: two relays in one binary
```
HUMAN + AGENT PATH ── NIP-01 over WebSocket ──────────────────────────────
parse JSON → BIP-340 verify → Postgres INSERT → FTS index → audit chain
└─ 34–37.7 µs ─┘ └────── the durability boundary ──────┘
ceiling: ~250–320k events/s per 16-core pod (verify-bound, estimate)
~10–30k/s once stored AND indexed (estimate)
MACHINE PATH ── opaque frames, ephemeral kinds, trusted link ────────────
read ~44 B fixed header → match key expression → forward bytes, unparsed
└─ no signature, no store, no index, no audit ─┘
ceiling: ~600k msg/s ≈ 0.44 Gbps in (estimate, not in tree)
SHARED: tenant fence · admission · interest routing · the bus
NOT SHARED: parsing · crypto · durability · query surface · client shape
```
The machine path's defining property is a refusal: **the relay never reads the
payload.** That is the enabling property for zero-copy fan-out, not a limitation
to work around — so anything the relay must act on has to live in the header
(community, kind, geo cell, conflation key, sequence, timestamp; ≈ 44 B fixed).
Content-aware work such as deduplication moves upstream to the feeder.
Accept the consequence deliberately: opaque machine frames are **not consumable
by a generic Nostr client**. Their consumers are purpose-built — a track
display, a fusion engine, a recorder.
---
## Ceilings, with profiles attached
| Profile | Figure | Basis |
| --- | --- | --- |
| Opaque pre-decoded frames · trusted link · never parsed · not stored | ~600k msg/s | **estimate** — the path is not yet in tree; the pre-/post-dedup question behind it is open at ~10× |
| Signed NIP-01 events · per 16-core pod · BIP-340 bound | ~250–320k events/s | **measured per-core, extrapolated** — `event_cost.rs` puts `verify_event` at 26.5–29.4k/s on one core (M3 Max, release) |
| Stored **and indexed** chat events · one Postgres | ~10–30k/s | **estimate** — persistence *latency* is measured (p95 74.6 ms direct, 77.1 ms nested) |
| Fan-out, per event | ~4.1 µs at N=1 → ~56 µs at N=64 | **measured** — `fanout_cost.rs`; past ~40 recipients fan-out exceeds signature verification |
| Bus interest scoping (Dragonfly) | 64× cluster ingress reduction | **measured** — `perf/relay_bus_scaling.py --mode redis` |
| Bus target (Zenoh) | ≥2M msg/s at 256 B, peer mode | **target, unproven** — gated on Phase 0 |
| Symmetric MAC vs. per-event signature | 179–382× faster | **measured** — HMAC-SHA256 0.19 µs, keyed BLAKE3 0.089 µs vs. 37.7 µs Schnorr |
Two consequences worth internalising before planning against these numbers:
- **At scale this system is fan-out bound, not crypto bound.** At 10M users /
1M concurrent, human message volume is ~3.3k events/s — one verification pod
covers it. Fan-out at 50 average recipients is ~1M frames/s.
- **The way past the verification ceiling is to skip verification** on links
that qualify for a trusted profile, never to make BIP-340 faster. Batch
Schnorr verification does not exist at any level of the pinned tree, and
measured on ed25519 — where batching does exist — batch-64 amortises to only
~2.9×.
Reproduce any of it:
```bash
cargo bench -p meridian-core --bench event_cost # BIP-340 ceiling, per core
cargo bench -p meridian-relay --bench fanout_cost # fan-out at N = 1 / 8 / 64
./perf/relay_bus_scaling.py --mode redis # interest-scoping reduction
```
---
## What Meridian replaces, and what stays at the edge
The claim is narrower than "broker replacement", and the narrowing is ratified
in [DIAGRAM.md § Part III](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/DIAGRAM.md) by the Architecture & Scale council.
| Replaced by Meridian | Kept at the edge (a broker, legitimately) |
| --- | --- |
| The mandatory Kafka hop on every message | Broker-held offline queues and persistent sessions |
| Per-message topic-ACL authorization | MQTT QoS 1/2 delivery state for constrained devices |
| A second durable log beside the query store | Retained messages and Last Will & Testament |
| Topic-prefix multi-tenancy | Shared subscriptions (`$share/group/topic`) |
| Unauthenticated-past-the-broker messages | The embedded MQTT client SDK ecosystem |
The right-hand column is a **standing architectural boundary**, not a gap list
to close. A device that has been offline for a day needs broker-held state; a
Meridian client re-runs a query over stored events, which works for a chat
client and does not work for a constrained device that cannot page history.
The topology that follows is **hub-and-leaf**: devices → edge broker/leaf →
feeder (decode, dedup, routing header, MAC or sign, batch) → authoritative
spine. The boundary is one-directional. The spine ingests from the edge; **the
edge never routes for the spine.**
The one irreducible difference: an MQTT message is authenticated by its
*connection*, so downstream of the broker nothing proves authorship. A signed
event carries its own proof to every consumer, forever. That is what the ~37.7 µs
buys, and it is what the audit chain, third-party verification and any future
federation rest on.
---
## System shape
```mermaid
flowchart TB
classDef client fill:#4a4a4a,stroke:#2b2b2b,color:#fff
classDef relay fill:#b03030,stroke:#6e1c1c,color:#fff
classDef store fill:#1e7a45,stroke:#0f4527,color:#fff
subgraph CL["CLIENT TIER — NIP-01 JSON and a narrow HTTP surface, nothing else"]
direction LR
D["Desktop · Tauri 2 + React 19"]:::client
M["Mobile · Flutter"]:::client
W["Web · repo browser + invite"]:::client
A["Agents · meridian-cli · ACP · dev-MCP"]:::client
end
subgraph RL["RELAY TIER — one Axum process, the ONLY enforcement point"]
direction TB
B0["community bind — resolve_host → TenantContext<br/>before AUTH, EVENT, REQ, REST, media, git"]:::relay
B1["admission · NIP-42 / NIP-98"]:::relay
B2["EVENT — kind gate · BIP-340 verify · scope · membership"]:::relay
B3["REQ — access checked BEFORE registration"]:::relay
B4["SubscriptionRegistry — 3-tier fan-out index"]:::relay
B0 --> B1 --> B2 --> B4
B1 --> B3 --> B4
end
subgraph ST["STACK TIER — one system of record per fact"]
direction LR
PG[("Postgres 17 — THE EVENT LOG<br/>events · members · workflows · audit · FTS")]:::store
DF[("Dragonfly — STATE, never events<br/>pub/sub · presence · rate windows")]:::store
S3[("MinIO / S3 — BYTES, never events<br/>media blobs · git objects")]:::store
end
CL --> RL
RL <--> PG
RL <--> DF
RL <--> S3
```
| Tier | Owns | Must never |
| --- | --- | --- |
| **Client** | Rendering, drafts, local settings, key custody | Hold authority, or talk to anything but the relay |
| **Relay** | Community binding, admission, verification, ordering, membership, fan-out | Delegate an access decision — it is the only enforcement point |
| **Postgres** | The event log and every fact derived by transaction | Be second. Nothing else may claim truth for a fact it stores |
| **Dragonfly** | Ephemeral state with a TTL, plus cross-pod delivery | Become a durable log |
| **Object store** | Bytes too large for a row | Hold anything the relay must interpret to decide |
The relay orchestrates every subsystem by direct call and **the subsystems never
call each other** — `meridian-workflow` never calls `meridian-pubsub`,
`meridian-search` never calls `meridian-db`. Every cross-subsystem interaction
is a line of code in the relay, which is why one process can be reasoned about.
---
## Design Law
Binding constraints on new protocol, identity and access-control surface. Each
is cheap to honour up front, expensive to retrofit, and written down because the
failure it prevents is silent rather than loud. Full text in
[AGENTS.md § Design Law](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/AGENTS.md); the conformance register is
[DIAGRAM.md § Part II](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/DIAGRAM.md).
| Law | What it forbids |
| --- | --- |
| **Names never encode ownership** | `org/team/channel` paths in repo, topic or namespace keys — a reorg becomes a fleet-wide rename |
| **Standing is registry-derived and effective-dated** | Baking org or role into a credential; membership is `[since, until)`, never a frozen claim |
| **Add attributes, not mechanisms** | A policy DSL or rules engine. New capability = new attribute + new event kind |
| **No third shim** | A mapping table or sync job between two enforcement points — one grant store, everyone reads it |
| **Explicit denial, never a silent empty result** | A decision that cannot name the record that made it |
| **Nothing is resolved until deployed and re-probed** | Closing work on green CI alone |
| **No vocabulary without an enforcement point** | A kind, tag or grant name nothing reads — enforced by `just check-kinds` |
| **Revocation is monotonic and absorbing** | Timestamp-wins resolution that could resurrect a revoked grant. Decided now, built at the second node — before any federation, never after |
| **Scale by replica / function / tenant / traffic class** | Sharding by kind or NIP. A kind is a column in every shard, never a shard |
**Refusals, declined by citation rather than re-argued** — a second durable log
behind the relay (`R2`), a second read path for data the spine stores (`R3`),
sharding telemetry kinds onto their own relays (`R1`), the edge relay peering
with the spine (`R4`), caching grants at the bridge (`R5`), and building
machinery for load nobody has measured yet (`R8`).
---
## Human and agent surface
The same event log, the same identity model, the same audit trail — whether the
author is a person or a process. Agents get their own keypairs, their own
channel memberships and their own audit trail, which is what makes them scoped
by identity rather than by permission flags.
| Surface | State |
| --- | --- |
| Relay, channels, threads, DMs, canvases, media, search, audit chain | **shipping** |
| Desktop app (Tauri 2 + React 19) | **shipping** |
| `meridian-cli` — agent-first, JSON in / JSON out — and the ACP harness (Goose, Codex, Claude Code) | **shipping** |
| YAML workflows — message / reaction / schedule / webhook triggers | **shipping** |
| Git hosting + NIP-34 events (patches, repo announcements, status), Nostr-signed push | **shipping** |
| Huddles — WebSocket Opus voice relay, no external SFU | **shipping** (recording, per-track publishing planned) |
| Meridian Mesh — relay-gated shared AI compute over iroh, OpenAI-compatible to agents | **shipping** |
| Mobile (Flutter, iOS + Android) | **in development** |
| Workflow approval gates | **partial** — schema, API, MCP tool and UI exist; the executor does not yet suspend and resume |
| Push notifications, developer portal | **designed** |
<details>
<summary><strong>Screenshots</strong></summary>
<table>
<tr>
<td width="50%" valign="top">
<img src="docs/assets/screenshots/channel-agents.png" alt="People and agents collaborating in a Meridian engineering channel and reacting with emoji" width="100%"><br>
<sub><strong>Agents are members, not bots.</strong> Add an agent to a channel the same way you add a person.</sub>
<img src="https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/raw/branch/main/docs/assets/screenshots/channel-agents.png" alt="People and agents collaborating in a Meridian engineering channel" width="100%"><br>
<sub><strong>Agents are members, not bots.</strong> Added to a channel the same way a person is.</sub>
</td>
<td width="50%" valign="top">
<img src="docs/assets/screenshots/create-channel.png" alt="The Add a channel dialog with search, filters, and channels to join or create" width="100%"><br>
<sub><strong>Spin up a room in seconds.</strong> Name it, describe it, make it private.</sub>
<img src="https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/raw/branch/main/docs/assets/screenshots/create-channel.png" alt="The Add a channel dialog with search, filters, and channels to join or create" width="100%"><br>
<sub><strong>Rooms are cheap.</strong> Name it, describe it, scope it.</sub>
</td>
</tr>
<tr>
<td colspan="2" valign="top">
<img src="docs/assets/screenshots/media-comments.png" alt="A video playing in Meridian with frame-anchored comments in a side panel" width="100%"><br>
<sub><strong>Media you can talk about.</strong> Leave comments pinned to specific frames.</sub>
<img src="https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/raw/branch/main/docs/assets/screenshots/media-comments.png" alt="A video playing in Meridian with frame-anchored comments in a side panel" width="100%"><br>
<sub><strong>Media with frame-anchored comments</strong>, stored via Blossom on S3/MinIO.</sub>
</td>
</tr>
</table>
---
## Why Meridian is better
One community. One identity model. One event log. Humans, agents, workflows, and repos all speak the same protocol, sign with the same kind of key, and end up in the same search index. In the default self-hosted deployment, one relay hosts one community; in a hosted multi-tenant deployment, each community keeps that same semantic boundary even when the backend shares Postgres, Redis, and object storage.
The bet is that one community can do what teams currently fake with chat, forges, bots, CI dashboards, release tools, search indexes, and a pile of glue code. Not all at once, not magically, but with one substrate instead of seven tabs pretending they know about each other.
Agents are part of the room, not haunted cron jobs.
---
## Three little stories
**Incident memory.** It's 2am. You type *"have we seen this error before?"* An agent watching the channel pulls six months of history, posts the threads, the root causes, the fixes, and offers to page whoever shipped the last one. The whole exchange — question, answer, evidence — stays in the channel.
**Branch as room.** You open a feature branch. A channel appears. Patches land as NIP-34 events, CI posts results, an agent runs a first-pass review, teammates react to the parts they care about, and the merge decision lands in the same room as the evidence.
**A release that writes itself.** A workflow fires on a tag. An agent reads the merged PRs from the project channels, drafts the release notes, posts them for human review, gets a 👍 reaction, and ships. Every step signed. Every step searchable.
---
## Works today · Being wired up · Strong opinions, pending code
| ✅ Works today | 🚧 Being wired up | 💭 Strong opinions, pending code |
|---|---|---|
| Relay, channels, threads, DMs, canvases, media, search, audit log | Mobile clients (iOS + Android, Flutter) | Web-of-trust reputation across relays |
| Desktop app (Tauri + React) | Workflow approval gates (infra exists, glue still drying) | Push notifications |
| `meridian-cli` (agent-first, JSON in / JSON out) + ACP harness (Goose, Codex, Claude Code) | Huddle lifecycle events | Culture features |
| YAML workflows: message / reaction / schedule / webhook triggers | | |
| Git events (NIP-34: patches, repo announcements, status) | | |
| Git hosting backend | | |
<sub>Please do not plan your compliance program around the 💭 column yet. The <a href="VISION.md">VISION docs</a> are the long version of what we think this becomes.</sub>
---
## Getting started
New to Meridian? Pick the path that matches you.
### I just want to try the app
> **No packaged builds are published yet.** The signed macOS/iOS pipeline has not
> been replaced for this self-hosted deployment — see
> [RELEASING.md § Signed platform builds](RELEASING.md). Until it is, build from
> source below.
By default the app connects to `ws://localhost:3000`. To point it at a relay you're running or one someone shared with you, set `MERIDIAN_RELAY_URL` before launching, or switch the relay from inside the app. If you don't have a relay yet, follow **Build & run from source** below to stand one up locally.
### I want to build & run from source
See **Quick start** below — this is the developer / self-host path.
</details>
---
## Quick start
You'll need [Docker](https://docs.docker.com/get-docker/) and [Hermit](https://cashapp.github.io/hermit/) (or Rust 1.88+, Node 24+, pnpm 10+, `just`).
Requires [Docker](https://docs.docker.com/get-docker/) and
[Hermit](https://cashapp.github.io/hermit/), which pins the whole toolchain
(Rust, Node, pnpm, `just`) and downloads it on first use.
**Once:**
```bash
git clone https://git.office.ilab.zone/RAID/R2D2-MERIDIAN.git && cd meridian
. ./bin/activate-hermit # pinned toolchain (tools auto-download on first use)
just setup && just build
git clone https://git.office.ilab.zone/RAID/R2D2-MERIDIAN.git
cd R2D2-MERIDIAN
. ./bin/activate-hermit # pinned toolchain — do this first, always
cp .env.example .env
./run.sh doctor # toolchain, Docker, port conflicts, stale processes, env drift
./run.sh all # services + relay + web in background, desktop in foreground
```
`just setup` runs `just bootstrap` automatically — it copies `.env.example` to `.env` if needed, downloads all required tools via Hermit, and starts Docker services + migrations.
`run.sh` wraps `just`; it does not replace it. What it adds is port resolution —
every port in the profile is probed by attempting a bind and walked upward until
free, then written to the two existing override layers (`.env.local` and
`docker-compose.override.yml`) so builds stay cache-warm. On a machine running
several stacks, that removes an entire class of quiet failure: a lost port bind,
or a relay dialling `:5432` and reaching someone else's database.
Prefer the raw recipes for split-terminal work:
**Every day:**
```bash
. ./bin/activate-hermit
just dev # starts the relay + desktop app together
just setup # deps, Docker services, migrations
just relay # relay on ws://localhost:3000
just desktop-dev # web-only dev server (fast iteration)
just dev # full Tauri app with native shell
just ci # the complete local gate — run before every PR
```
Relay on `ws://localhost:3000`. Desktop app pops up. You're in.
For agents, set `MERIDIAN_PRIVATE_KEY` and `MERIDIAN_RELAY_URL`, then drive
everything through [`meridian-cli`](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/crates/meridian-cli) — JSON on stdout,
structured errors on stderr, designed for tool calls. The ACP harness injects
both variables into managed agent subprocesses automatically.
For a split-terminal workflow (relay logs separate from Vite output), use `just relay` in one terminal and `just desktop-dev` in another.
Deploying rather than developing? Use the production Compose bundle in
[`deploy/compose/`](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/deploy/compose/README.md) or the Helm charts in
[`deploy/charts/`](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/deploy/AGENTS.md). The root `docker-compose.yml` is for
day-to-day development only.
Want a single-node / VPS relay instead of the local-dev stack? Use the production Compose bundle in [`deploy/compose/`](deploy/compose/README.md) (`docker compose` + Postgres, Redis, MinIO, optional Caddy/TLS). The root [`docker-compose.yml`](docker-compose.yml) is for day-to-day development only.
<details>
<summary><strong>Windows prerequisites</strong></summary>
For agents, set `MERIDIAN_PRIVATE_KEY` and use [`meridian-cli`](crates/meridian-cli) — JSON in, JSON out, designed for LLM tool calls.
The agent shell tool runs commands under bash. Install
[Git for Windows](https://git-scm.com/download/win) — Meridian resolves Git Bash
at runtime. To point it at a different bash-compatible shell, set
`MERIDIAN_SHELL` to its path; the agent's tool description updates to match.
</details>
---
## Windows prerequisites
The agent shell tool runs commands under bash. On macOS and Linux that's already there; on Windows you need to bring it.
Install [Git for Windows](https://git-scm.com/download/win) — it ships Git Bash, which is what meridian resolves at runtime. Once it's installed, everything works the same as on other platforms.
If you'd rather point meridian at a different bash-compatible shell, set `MERIDIAN_SHELL` to its path (e.g. `MERIDIAN_SHELL=C:\path\to\bash.exe`). The agent's tool description updates automatically to reflect whichever shell is active.
---
## Architecture
## Repository map
```
┌─────────────────────────────────────────────────────────────────────────┐
│ Clients │
│ Human client AI agent CLI / scripts │
│ (Meridian desktop) (Goose, Codex, ...) (meridian-cli, agents) │
│ │ ┌──────────────┐ │ │
│ │ │ meridian-acp │ │ │
│ │ │ (ACP ↔ MCP) │ │ │
│ │ └──────┬───────┘ │ │
│ │ │ │ │
└───────┼──────────────────────┼───────────────────────┼──────────────────┘
│ WebSocket │ WS + REST │ WS + REST
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────┐
│ meridian-relay │
│ NIP-01 · NIP-42 auth · channel/DM/media/workflow/git REST · audit log │
└───┬──────────────────────────┬──────────────────────────┬───────────────┘
│ │ │
┌──▼───────────┐ ┌──────▼──────┐ ┌───────▼─────┐
│ Postgres │ │ Redis │ │ S3/MinIO │
│ (events + │ │ (pub/sub) │ │ (Blossom) │
│ FTS search) │ └─────────────┘ └─────────────┘
└──────────────┘
crates/ Rust workspace — relay, protocol libraries, agent surface, tooling
desktop/ Tauri 2 + React 19 desktop app
web/ Browser client (repo browser, invite accept) served by the relay
mobile/ Flutter app — Riverpod + hooks
migrations/ Forward-only Postgres schema (auto-applied on relay startup)
docs/ Draft NIPs, TLA+/Tamarin specs, operator guides, benchmarks
deploy/ Helm charts and the production Compose stack
perf/ Bus scaling harness
benchmarks/ harbor-meridian-orchestra multi-agent benchmark
scripts/ Dev tooling, lint guard cores, release and contract scripts
```
A Rust workspace of focused crates. Single source of truth: the relay. See [ARCHITECTURE.md](ARCHITECTURE.md) for the full breakdown.
<details>
<summary><strong>Crate map</strong></summary>
**Core protocol** — `meridian-core` (zero-I/O types, NIP-01 filters, Schnorr verify) · `meridian-relay` (Axum WS + REST)
**Relay and core** — `meridian-relay` (Axum WS + REST; also hosts git and huddle
audio) · `meridian-core` (zero-I/O types, filter matching, Schnorr verify, the
kind registry) · `meridian-db` (Postgres event store) · `meridian-auth`
(NIP-42/98) · `meridian-pubsub` (Dragonfly fan-out, presence, typing) ·
`meridian-search` (Postgres FTS) · `meridian-audit` (hash-chain log) ·
`meridian-media` (Blossom/S3) · `meridian-relay-mesh` (shared compute) ·
`meridian-control-plane` · `meridian-push-gateway`
**Services** — `meridian-db` (Postgres) · `meridian-auth` (NIP-42/98 Schnorr auth, rate limiting) · `meridian-pubsub` (Redis, presence, typing) · `meridian-search` (Postgres FTS) · `meridian-audit` (hash-chain log). Multi-community mode scopes tenant-observable rows, cache keys, search documents, workflow state, media metadata, git repo pointers, and audit chains by the host-derived community; shared infrastructure is an implementation detail, not a user-visible global workspace.
**Agent surface** — `meridian-cli` (agent-first CLI) · `meridian-acp` (ACP
harness) · `meridian-agent` (minimal ACP-compliant agent) · `meridian-dev-mcp`
(shell + file-edit tools) · `meridian-workflow` (YAML-as-code engine) ·
`meridian-persona` (persona packs) · `meridian-harness` (all-in-one bundle)
**Agent surface** — `meridian-cli` (agent-first CLI, JSON in / JSON out) · `meridian-acp` (ACP harness for Goose/Codex/Claude Code) · `meridian-agent` (ACP agent — see [VISION_AGENT.md](VISION_AGENT.md)) · `meridian-dev-mcp` (shell + file-edit tools) · `meridian-workflow` (YAML automation) · `meridian-persona` (agent persona packs)
**Git and pairing** — `git-sign-nostr` · `git-credential-nostr` ·
`meridian-pair-relay` · `meridian-pairing-cli`
**Git & pairing** — `git-sign-nostr` / `git-credential-nostr` (nostr-signed git) · `meridian-pair-relay` / `meridian-pairing-cli` (relay pairing)
**Shared and tooling** — `meridian-sdk` (typed event builders) ·
`meridian-ws-client` · `meridian-admin` (operator CLI) · `meridian-conformance` ·
`meridian-test-client` (E2E suite)
On macOS, configure `git-credential-nostr` with a host-scoped empty helper
entry before the `nostr` entry; this resets the inherited `osxkeychain` helper
and prevents spurious `fatal: failed to store` output on successful operations.
See the [credential-helper setup](crates/git-credential-nostr/README.md#setup).
**Shared** — `meridian-sdk` (typed event builders) · `meridian-media` (Blossom/S3)
**Tooling** — `meridian-admin` (admin CLI) · `meridian-test-client` (E2E)
On macOS, configure `git-credential-nostr` with a host-scoped empty helper entry
before the `nostr` entry — this resets the inherited `osxkeychain` helper and
prevents spurious `fatal: failed to store` output on success. See the
[credential-helper setup](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/crates/git-credential-nostr/README.md#setup).
</details>
---
## Going further
## Protocol surface
- **[VISION.md](VISION.md)** · **[VISION_SOVEREIGN.md](VISION_SOVEREIGN.md)** · **[VISION_PROJECTS.md](VISION_PROJECTS.md)** · **[VISION_AGENT.md](VISION_AGENT.md)** — the four vision docs
- **[ARCHITECTURE.md](ARCHITECTURE.md)** — system design, kind ranges, subsystem boundaries
- **[TESTING.md](TESTING.md)** — multi-agent E2E test suite
- **[CONTRIBUTING.md](CONTRIBUTING.md)** · **[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)** · **[SECURITY.md](SECURITY.md)** · **[GOVERNANCE.md](GOVERNANCE.md)**
NIP-01 over WebSocket is the primary API. Everything is an event; a new
capability is a new kind integer in `meridian-core/src/kind.rs` plus a handler,
never a new endpoint-specific JSON API. That buys realtime fan-out, NIP-29
scoping and the existing auth pipeline for free.
<details>
<summary><strong>Configuration</strong> (env vars, defaults work for local dev)</summary>
The HTTP surface is deliberately narrow and preserves the same host-derived
community boundary: NIP-11/NIP-05 metadata, `POST /events`, `POST /query`,
`POST /count`, workflow webhooks, Blossom media, git smart HTTP, git policy
hooks, health probes.
All defaults work out of the box. Override via `.env`. Full reference in [`.env.example`](.env.example).
Repo-local extensions live as draft NIPs in [`docs/nips/`](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/docs/AGENTS.md), with
TLA+ and Tamarin models for the multi-tenant isolation and authorization
guarantees in [`docs/formal/`](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/docs/AGENTS.md). `just check-kinds` fails CI on
any kind, tag or grant name that no enforcement point reads — declared
vocabulary without an enforcement point is the standing risk when a repo carries
this many drafts.
</details>
---
<details>
<summary><strong>Common dev commands</strong></summary>
## Program and roadmap
- **[DIAGRAM.md](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/DIAGRAM.md)** is the system view: Part I the running system,
Part II the GOAT/EFDI conformance register, Part III the throughput case
against a central broker, Part IV the maturation map from *one relay that does
everything* to a thin spine plus independently deployable consumers — adding
no second read path, no second policy store, and no client-visible protocol
change.
- **[TASKS.md](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/TASKS.md)** is the 10-week decentralized-relay program plan that
executes Part III's ratified call: a frozen MIP specification suite, a
reference implementation of the opaque-frame data plane, an MQTT compatibility
bridge at the edge, and a conformance suite. It mirrors Bead IDs; it never
leads them.
- **Beads is the source of truth for task state.** `bd ready` for available
work, `bd show <id>` for any ID cited in the docs. Do not keep a parallel TODO
list.
The live gate is measurement, not design: the Zenoh Phase 0 benchmark either
substantiates the bus premise or kills it, and the opaque-frame path must be
measured before anything downstream is optimised. Machinery built for load
nobody has measured is inventory (`R8`).
---
## Quality gates
```bash
just setup # Docker, migrations, desktop deps
just relay # Run the relay
just dev # Run the desktop app
just build # Build the Rust workspace
just check # fmt + clippy + desktop check
just test-unit # Unit tests (no infra required)
just test # Full suite (starts services if needed)
just ci # Everything CI runs
just reset # ⚠️ Wipe data + recreate
just ci # fmt + clippy + desktop lint + unit tests + builds
just test-unit # unit tests, no infrastructure
just test # integration suite (requires Postgres + Dragonfly)
just check # every guard: kinds, skills, brand, migrations, contracts
```
</details>
Read the **exit code**, not the output — piping a gate into `tail` or `grep`
reports the filter's status, so a failed run looks clean. Clippy passing does not
mean fmt passes, and a green `cargo test` says nothing about the lint gate: a
test build compiles through an unused import that `-D warnings` rejects.
Pre-commit hooks auto-fix formatting and re-stage; pre-push runs clippy and fast
unit tests. Commit with `git commit -s` — the DCO check fails any PR with a
commit missing a `Signed-off-by` trailer.
Additional standing rules: no `unsafe`; no new `unwrap()` or `expect()` in
production paths; new public API carries doc comments.
---
## What it is not
## What we deliberately do not build
- Not blockchain. Signed events are useful without making everyone buy a commemorative coin.
- Not an AI replacement plan. Meridian works best when humans stay in the loop and agents stay in the room.
- Not finished. We will tell you what works and what doesn't.
- **A second system of record.** Postgres holds the events. Derived views are
legitimate downstream of the spine — cursor-bearing, freshness-stamped, and
invisible at the NIP-01 edge — but nothing else claims truth for a fact the
spine stores.
- **A policy engine.** Grants are enumerable dated rows precisely so that a
denial can name the record that decided it. A rule- or formula-based DSL is
un-auditable by enumeration, and is refused by name.
- **Federation before monotonic revocation.** Multi-master peering would let a
concurrent grant resurrect a revoked one by wall-clock timestamp. The defect is
dormant while a single relay is the only writer; the fix lands *before* the
second writer, because after is too late and the resurrection is silent.
- **A throughput number without its profile.** Including in this file.
**What it is:** one relay where humans, agents, workflows, git events, and project memory cooperate — the beginning of a workspace that can grow past the tabs it replaces.
---
## Documentation
| Document | Covers |
| --- | --- |
| [ARCHITECTURE.md](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/ARCHITECTURE.md) | Component reference — crates, pipelines, kind ranges, subsystem boundaries |
| [DIAGRAM.md](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/DIAGRAM.md) | System view, conformance register, throughput case, maturation map |
| [TASKS.md](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/TASKS.md) | The 10-week decentralized-relay program |
| [AGENTS.md](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/AGENTS.md) | Design Law, agent conventions, the STELLAR doc hierarchy |
| [CONTRIBUTING.md](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/CONTRIBUTING.md) | Setup, code style, PR process, how to add kinds / commands / endpoints |
| [TESTING.md](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/TESTING.md) | Multi-agent E2E guide |
| [RELEASING.md](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/RELEASING.md) | Release flow, candidate tags, deployment provenance |
| [SECURITY.md](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/SECURITY.md) · [GOVERNANCE.md](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/GOVERNANCE.md) · [CODE_OF_CONDUCT.md](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/CODE_OF_CONDUCT.md) | Disclosure, decision rights, conduct |
| [VISION.md](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/VISION.md) and companions | Where the product is going: [Sovereign](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/VISION_SOVEREIGN.md) · [Projects](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/VISION_PROJECTS.md) · [Agents](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/VISION_AGENT.md) · [Mesh](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/VISION_MESH.md) · [Activity](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/VISION_ACTIVITY.md) · [Moderation](https://git.office.ilab.zone/RAID/R2D2-MERIDIAN/src/branch/main/VISION_MODERATION.md) |
---
<p align="center">
<sub>Meridian</sub><br>
<sub>Apache 2.0 · Built by <a href="https://block.xyz">Block, Inc.</a></sub>
<sub>Meridian · MIT · Built by <strong>STELLAR</strong></sub>
</p>

View file

@ -230,7 +230,7 @@ Greenfield. Agent swarms build in parallel, integrating at the event store bound
## Contributing
See [README.md](README.md) for setup and [AGENTS.md](AGENTS.md) for connecting AI agents. Licensed under Apache-2.0.
See [README.md](README.md) for setup and [AGENTS.md](AGENTS.md) for connecting AI agents. Licensed under MIT.
---

View file

@ -337,4 +337,4 @@ See the [root TESTING.md](../../TESTING.md) for the full integration testing gui
## License
Apache-2.0
MIT

View file

@ -3,7 +3,7 @@ name = "meridian-persona"
version = "0.1.0"
edition = "2021"
description = "Parser and loader for Meridian persona pack files (.persona.md)"
license = "Apache-2.0"
license = "MIT"
repository = "https://git.office.ilab.zone/RAID/R2D2-MERIDIAN"
[dependencies]

View file

@ -39,7 +39,7 @@ allow = [
# assertion CBOR parsing and also transitively by appattest.
"BlueOak-1.0.0",
# bzip2/libbzip2's permissive BSD-like license. New via desktop zip/bzip2
# transitive deps; compatible with Apache-2.0 distribution.
# transitive deps; compatible with MIT distribution.
"bzip2-1.0.6",
]
confidence-threshold = 0.8
@ -81,7 +81,7 @@ license-files = []
[[licenses.clarify]]
crate = "meridian-desktop"
expression = "Apache-2.0"
expression = "MIT"
license-files = []
[licenses.private]

View file

@ -7,7 +7,7 @@ description: |
PostgreSQL and Redis. Configurable for single-node evaluation
(subcharts on) and HA production (external services, existingSecret).
type: application
version: 0.1.9
version: 0.1.10
appVersion: "0.1.0"
home: https://git.office.ilab.zone/RAID/R2D2-MERIDIAN
sources:
@ -19,13 +19,13 @@ keywords:
- websocket
- chat
maintainers:
- name: Block
url: https://github.com/block
- name: STELLAR
url: https://git.office.ilab.zone/RAID
annotations:
artifacthub.io/changes: |
- kind: added
description: Subscriber-aware readiness configuration, relay alert rules, and opt-in network policy profiles.
artifacthub.io/license: Apache-2.0
- kind: changed
description: Chart metadata relicensed to MIT and maintainer updated to STELLAR.
artifacthub.io/license: MIT
# Optional eval-only subcharts. Production deploys disable both and point
# externalPostgresql / externalRedis (or secrets.existingSecret) at managed