fix(rebrand): complete the conversion the rg-based checks missed
A `git grep` audit (which, unlike `rg`, does not skip dotfiles) found the sweep was incomplete in ways four green CI runs could not see. **Dotfiles were never in the rewrite lists.** The `/api/codebase` and `codebase.design` fixes built their file list from `rg -l`, so `.env.example` and `deploy/compose/.env.example` kept the old control-plane path and an escaped legacy host regex. `bin/git` was separately reverted to its Codebase-era error text by the `git checkout -- bin/` that repaired the clobbered Hermit symlinks. **The N-1 hop was dropped in two more places**, the same defect as codebaseChat-b8x, one generation on: - `e2e_git.rs` published `buzz-channel` + `codebase-chat-channel` on its kind:30617 fixtures, per the expand-window procedure in the schema-rollout runbook. The sweep rewrote the second rather than adding a third, so the fixture stopped exercising the generation that is actually N-1 here. All three are now emitted. The relay still reads only its native tag, which is the documented design: writers emit every live generation, readers read one. - The chart alert pack kept `buzz_*` fallbacks beside the then-current `codebase_chat_*` metrics. Renaming the current set to `meridian_*` left `buzz_*` — two generations back — as the only fallback, so a rolling upgrade would have matched neither on pods still emitting `codebase_chat_*`: exactly the observability blackout the fallback exists to prevent. The fallback now tracks the immediately-preceding generation, which is what "one retention window" in the chart README always meant. promtool passes. **Sprout-era runtime config**, which is operator-facing rather than persisted, now resolves through one `config::legacy_env_u64`/`_i64` helper that prefers `MERIDIAN_*` and falls back to `SPROUT_*`, so existing environments keep working. A single resolver is deliberate: `MAX_NOT_BEFORE_DELTA` is both enforced in ingest and advertised in NIP-11, and those drifting apart is the second-copy defect this rebrand keeps producing. Also: workspace/persona `repository` metadata off `block/sprout`; the "I work at Block" README section replaced with the honest no-packaged-builds note; the Block corporate-CA keychain export in the local deploy script replaced with a bring-your-own-bundle hatch; iOS `CFBundleURLName` and the theme/test locals that my bead-ID revert had left spelled `codebaseChat`. SECURITY.md carried **meridian@block.xyz**, which would have routed a report about this deployment to a third party. Flagged in-file with a TODO rather than silently pointed somewhere plausible. Apache-2.0 copyright and attribution to Block, Inc. are retained deliberately in LICENSE, ARCHITECTURE.md, the README footer, and the Goose logo credits — the license requires it and a rename does not transfer authorship. Verified: just ci exit 0; promtool SUCCESS; relay clippy -D warnings clean. Signed-off-by: Joshua Belke <joshua@innovationhub-act.org>
This commit is contained in:
parent
9cad3fb324
commit
c5c733d3ef
21 changed files with 142 additions and 75 deletions
|
|
@ -187,7 +187,7 @@ RELAY_URL=ws://localhost:3000
|
|||
# A packaged app launched from Finder, the Dock, or a deep link inherits no
|
||||
# shell environment, so a build that must create communities has to set these at
|
||||
# BUILD time — they are compiled in as a fallback to the runtime values.
|
||||
# MERIDIAN_CONTROL_PLANE_URL=http://127.0.0.1:8090/api/codebase
|
||||
# MERIDIAN_CONTROL_PLANE_URL=http://127.0.0.1:8090/api/meridian
|
||||
# MERIDIAN_CONTROL_PLANE_ORIGIN=http://127.0.0.1:8090
|
||||
|
||||
# Shared Redis-backed admission limits. Defaults shown below; each value must
|
||||
|
|
|
|||
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
|
|
@ -531,7 +531,7 @@ jobs:
|
|||
MERIDIAN_RATE_LIMIT_HUMAN_API_CALLS_PER_MIN=100000 \
|
||||
MERIDIAN_RATE_LIMIT_HUMAN_WS_EVENTS_PER_SEC=10000 \
|
||||
MERIDIAN_GIT_PROBE_WRITERS=8 \
|
||||
SPROUT_REMINDER_SCHEDULER_INTERVAL_SECS=1 \
|
||||
MERIDIAN_REMINDER_SCHEDULER_INTERVAL_SECS=1 \
|
||||
./target/ci/meridian-relay > /tmp/meridian-relay.log 2>&1 &
|
||||
echo $! > /tmp/meridian-relay.pid
|
||||
for attempt in $(seq 1 60); do
|
||||
|
|
@ -689,7 +689,7 @@ jobs:
|
|||
MERIDIAN_WORKFLOW_SECRET_KEY=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef \
|
||||
MERIDIAN_RECONCILE_CHANNELS=true \
|
||||
MERIDIAN_GIT_PROBE_WRITERS=8 \
|
||||
SPROUT_REMINDER_SCHEDULER_INTERVAL_SECS=1 \
|
||||
MERIDIAN_REMINDER_SCHEDULER_INTERVAL_SECS=1 \
|
||||
./target/ci/meridian-relay > /tmp/meridian-relay.log 2>&1 &
|
||||
echo $! > /tmp/meridian-relay.pid
|
||||
for attempt in $(seq 1 60); do
|
||||
|
|
|
|||
|
|
@ -645,11 +645,27 @@ self-hosted infrastructure rather than being renamed in place. 1826 files.
|
|||
| Repo slug | `codebase/codebase-chat` | `r2d2/meridian` |
|
||||
| Control-plane API base | `/api/codebase` | `/api/meridian` |
|
||||
|
||||
`sprout` is **not** swept. It is an older brand whose surviving references are
|
||||
stored identifiers (`sprout_agent_provider`, `xyz.block.sprout.app`,
|
||||
`sprout-workspaces`) plus the `sprig` crate. Renaming those breaks the same
|
||||
migrations the rules below protect. Only the `sprout-cli` skill was renamed, to
|
||||
`meridian-cli`, because it is tooling rather than stored state.
|
||||
`sprout` is **mostly** not swept. Its surviving references are stored
|
||||
identifiers (`sprout_agent_provider`, `xyz.block.sprout.app`,
|
||||
`sprout-workspaces`); renaming those breaks the same migrations the rules below
|
||||
protect. Three exceptions were converted because they are not stored state:
|
||||
|
||||
- the `sprout-cli` skill → `meridian-cli` (tooling, zero blast radius);
|
||||
- `repository = "https://github.com/block/sprout"` in the workspace and
|
||||
`meridian-persona` manifests → `r2d2/meridian`;
|
||||
- the runtime env knobs `SPROUT_MAX_NOT_BEFORE_DELTA`,
|
||||
`SPROUT_REMINDER_SCHEDULER_{INTERVAL_SECS,BATCH_LIMIT}`, which are
|
||||
operator-facing configuration rather than persisted data. They now resolve
|
||||
through `config::legacy_env_u64`/`_i64`, which reads `MERIDIAN_*` first and
|
||||
falls back to `SPROUT_*`, so an existing environment keeps working. One
|
||||
resolver rather than four inline reads is deliberate:
|
||||
`MAX_NOT_BEFORE_DELTA` is both *enforced* in ingest and *advertised* in
|
||||
NIP-11, and those two drifting apart is the classic second-copy defect.
|
||||
|
||||
Still carrying the Sprout lineage, and **an open decision**: the `sprig` crate
|
||||
— the all-in-one ACP/agent/dev-MCP harness. "Sprig" is a Sprout diminutive, but
|
||||
it names a shipped binary, a Docker image, and `.github/workflows/sprig.yml`,
|
||||
so renaming it is an outward-facing change rather than a sweep.
|
||||
|
||||
### The symbol is now a pixel M — and its proportion is a constraint
|
||||
|
||||
|
|
@ -789,6 +805,35 @@ Recorded because each cost real time and none is obvious:
|
|||
that shipped them; new vocabulary gets a new migration and a new assertion
|
||||
block. This is the same defect as the retired-Fizz fixtures in § 2, one level
|
||||
further out.
|
||||
- **`rg` skips dotfiles; `git grep` does not.** Every *sweep* was correct
|
||||
because it drove off `git ls-files`, but several targeted *fixes* built their
|
||||
file list from `rg -l` — which silently excludes `.env.example`,
|
||||
`deploy/compose/.env.example`, `.github/`, and every other dotpath. Two
|
||||
config files kept `/api/codebase` and an escaped `codebase.design` through
|
||||
four green CI runs because of this. **Audit with `git grep`**, and never
|
||||
build a rewrite list from `rg` without `--hidden`.
|
||||
- **Restoring a file from git can silently undo the sweep.**
|
||||
`git checkout -- bin/` (repairing the clobbered Hermit symlinks) also reverted
|
||||
`bin/git`, a real tracked script, back to its Codebase-era error message.
|
||||
After any `git checkout` during a rename, re-audit the paths you restored.
|
||||
- **The N-1 hop got dropped in three more places, each the same shape.** The
|
||||
rule "every rename prepends, never replaces" is not limited to app-data
|
||||
directories:
|
||||
- `e2e_git.rs` published `buzz-channel` + `codebase-chat-channel` on its
|
||||
kind:30617 fixtures, per the expand-window procedure in
|
||||
`docs/runbooks/relay-schema-rollout.md`. The sweep rewrote the *second*
|
||||
rather than adding a third, so the fixture stopped exercising the
|
||||
generation that is actually N-1 for this rollout.
|
||||
- The chart's alert pack carried `buzz_*` fallbacks beside the then-current
|
||||
`codebase_chat_*` metrics. The sweep renamed the current set to
|
||||
`meridian_*` and left `buzz_*` — two generations back — as the only
|
||||
fallback, so a rolling upgrade would have matched neither on pods still
|
||||
emitting `codebase_chat_*`. That is precisely the observability blackout
|
||||
the fallback exists to prevent. Fixed by moving the fallback to the
|
||||
immediately-preceding generation, which is what "one retention window" in
|
||||
the chart README always meant.
|
||||
- Migration `0031` had to be written to dual-read *all three* generations,
|
||||
not just the newest two.
|
||||
- **A shorter name reflows code and exposes latent lints.** `meridian_core` is
|
||||
shorter than `codebase_chat_core`, so rustfmt collapsed a block-bodied closure
|
||||
in `ingest.rs` onto one line — and `clippy::nonminimal_bool` only fires on the
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
rust-version = "1.88.0"
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/block/sprout"
|
||||
repository = "https://github.com/r2d2/meridian"
|
||||
|
||||
[workspace.dependencies]
|
||||
# Runtime
|
||||
|
|
|
|||
11
README.md
11
README.md
|
|
@ -115,16 +115,13 @@ New to Meridian? Pick the path that matches you.
|
|||
|
||||
### I just want to try the app
|
||||
|
||||
Grab a packaged build from the [latest release](https://github.com/r2d2/meridian/releases/latest) — macOS (`.dmg`), Linux (`.AppImage` / `.deb`), or Windows (`.exe`). Install it like any other 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 work at Block
|
||||
|
||||
Don't build from source, and don't use the OSS release — use the internal build. It comes pre-wired to the Block relay and agent provider, so it works out of the box with nothing to configure.
|
||||
|
||||
Download the latest build from [`squareup/meridian-releases` releases](https://github.com/squareup/meridian-releases/releases/latest) and install it.
|
||||
|
||||
### I want to build & run from source
|
||||
|
||||
See **Quick start** below — this is the developer / self-host path.
|
||||
|
|
|
|||
|
|
@ -4,8 +4,14 @@
|
|||
|
||||
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||
|
||||
> **⚠ The reporting address below is not yet configured for this deployment.**
|
||||
> It previously routed to Block, which no longer operates this fork — sending a
|
||||
> report there would disclose a vulnerability in *your* deployment to a third
|
||||
> party. Set a real contact before publishing this repo anywhere.
|
||||
|
||||
If you discover a security vulnerability in Meridian, please report it by emailing
|
||||
**meridian@block.xyz**. Include as much detail as possible:
|
||||
**security@meridian.r2d2.office.ilab.zone** (TODO: confirm this mailbox exists
|
||||
and is monitored). Include as much detail as possible:
|
||||
|
||||
- A description of the vulnerability and its potential impact
|
||||
- Steps to reproduce or a proof-of-concept (if available)
|
||||
|
|
|
|||
2
bin/git
2
bin/git
|
|
@ -37,7 +37,7 @@ version_at_least() {
|
|||
}
|
||||
|
||||
if ! version_at_least "${installed_version}" "${minimum_version}"; then
|
||||
echo "error: Git ${minimum_version} or newer is required for Codebase Chat Nostr authentication (found ${installed_version})" >&2
|
||||
echo "error: Git ${minimum_version} or newer is required for Meridian Nostr authentication (found ${installed_version})" >&2
|
||||
if [[ "$(uname -s)" == "Darwin" ]]; then
|
||||
echo "Install a current Git (for example, 'brew install git'), then reactivate Hermit." >&2
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -646,7 +646,7 @@ pub const MAX_TOOL_RESULT_BYTES: usize = 8 * 1024 * 1024;
|
|||
/// Default cap on the *text* portion of a single tool result. Oversized text
|
||||
/// is middle-elided before it enters history; without this, one fat `cat`
|
||||
/// burns the context window and forces a lossy handoff. 50 KiB matches the
|
||||
/// shell-output caps in sprout-dev-mcp, goose, and pi; codex defaults to
|
||||
/// shell-output caps in meridian-dev-mcp, goose, and pi; codex defaults to
|
||||
/// 10 KB. Tunable via `MERIDIAN_AGENT_MAX_TOOL_RESULT_TEXT_BYTES`.
|
||||
pub const DEFAULT_TOOL_RESULT_TEXT_BYTES: usize = 50 * 1024;
|
||||
pub const MAX_TOOL_CALLS_PER_TURN: usize = 64;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
description = "Parser and loader for Meridian persona pack files (.persona.md)"
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/block/sprout"
|
||||
repository = "https://github.com/r2d2/meridian"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
|
|
|
|||
|
|
@ -1106,6 +1106,35 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
/// Read a numeric setting from `MERIDIAN_<name>`, falling back to the retired
|
||||
/// `SPROUT_<name>` spelling.
|
||||
///
|
||||
/// A handful of relay knobs were never renamed past the Sprout generation, so
|
||||
/// an operator's existing environment still spells them `SPROUT_*`. Dropping
|
||||
/// that spelling would silently revert the knob to its default rather than
|
||||
/// fail — the same failure mode the GUC and app-data bridges exist to prevent —
|
||||
/// so both are read, current name first.
|
||||
///
|
||||
/// This is the single resolver for these values on purpose:
|
||||
/// `SPROUT_MAX_NOT_BEFORE_DELTA` is both *enforced* in the ingest path and
|
||||
/// *advertised* in NIP-11, and those two must not drift apart.
|
||||
pub fn legacy_env_u64(name: &str, default: u64) -> u64 {
|
||||
std::env::var(format!("MERIDIAN_{name}"))
|
||||
.or_else(|_| std::env::var(format!("SPROUT_{name}")))
|
||||
.ok()
|
||||
.and_then(|value| value.parse().ok())
|
||||
.unwrap_or(default)
|
||||
}
|
||||
|
||||
/// Signed variant of [`legacy_env_u64`].
|
||||
pub fn legacy_env_i64(name: &str, default: i64) -> i64 {
|
||||
std::env::var(format!("MERIDIAN_{name}"))
|
||||
.or_else(|_| std::env::var(format!("SPROUT_{name}")))
|
||||
.ok()
|
||||
.and_then(|value| value.parse().ok())
|
||||
.unwrap_or(default)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
|||
|
|
@ -1341,11 +1341,9 @@ fn validate_event_reminder(event: &Event) -> Result<(), &'static str> {
|
|||
// omit it. The ordering check only applies when both are present.
|
||||
if let Some(nb) = not_before {
|
||||
// Reject reminders scheduled beyond the configured horizon. The same
|
||||
// SPROUT_MAX_NOT_BEFORE_DELTA env var is advertised in NIP-11.
|
||||
let max_delta: u64 = std::env::var("SPROUT_MAX_NOT_BEFORE_DELTA")
|
||||
.ok()
|
||||
.and_then(|v| v.parse().ok())
|
||||
.unwrap_or(31_536_000); // 1 year default
|
||||
// MAX_NOT_BEFORE_DELTA setting is advertised in NIP-11 — both read it
|
||||
// through `config::legacy_env_u64`, so they cannot drift.
|
||||
let max_delta = crate::config::legacy_env_u64("MAX_NOT_BEFORE_DELTA", 31_536_000); // 1 year default
|
||||
let now = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap_or_default()
|
||||
|
|
|
|||
|
|
@ -830,14 +830,10 @@ async fn main() -> anyhow::Result<()> {
|
|||
// column: only the pod that wins the atomic claim publishes.
|
||||
{
|
||||
let scheduler_state = Arc::clone(&state);
|
||||
let scheduler_interval_secs: u64 = std::env::var("SPROUT_REMINDER_SCHEDULER_INTERVAL_SECS")
|
||||
.ok()
|
||||
.and_then(|v| v.parse().ok())
|
||||
.unwrap_or(10);
|
||||
let scheduler_batch_limit: i64 = std::env::var("SPROUT_REMINDER_SCHEDULER_BATCH_LIMIT")
|
||||
.ok()
|
||||
.and_then(|v| v.parse().ok())
|
||||
.unwrap_or(100);
|
||||
let scheduler_interval_secs =
|
||||
meridian_relay::config::legacy_env_u64("REMINDER_SCHEDULER_INTERVAL_SECS", 10);
|
||||
let scheduler_batch_limit =
|
||||
meridian_relay::config::legacy_env_i64("REMINDER_SCHEDULER_BATCH_LIMIT", 100);
|
||||
tokio::spawn(async move {
|
||||
info!(
|
||||
interval_secs = scheduler_interval_secs,
|
||||
|
|
|
|||
|
|
@ -147,10 +147,7 @@ pub struct RelayLimitation {
|
|||
/// `AuthState::Authenticated`. This is independent of the REST API token
|
||||
/// toggle (`config.require_auth_token`).
|
||||
fn relay_limitation(max_message_length: usize) -> RelayLimitation {
|
||||
let max_not_before_delta: u64 = std::env::var("SPROUT_MAX_NOT_BEFORE_DELTA")
|
||||
.ok()
|
||||
.and_then(|v| v.parse().ok())
|
||||
.unwrap_or(31_536_000); // 1 year default
|
||||
let max_not_before_delta = crate::config::legacy_env_u64("MAX_NOT_BEFORE_DELTA", 31_536_000); // 1 year default
|
||||
|
||||
RelayLimitation {
|
||||
max_message_length: Some(max_message_length as u64),
|
||||
|
|
|
|||
|
|
@ -307,6 +307,7 @@ async fn git_clone_push_fetch_force_roundtrip() {
|
|||
// current N reads the ownership-neutral name. Both bind the same
|
||||
// UUID, so there is one ACL fact and no synchronization shim.
|
||||
Tag::parse(["buzz-channel", &channel]).unwrap(),
|
||||
Tag::parse(["codebase-chat-channel", &channel]).unwrap(),
|
||||
Tag::parse(["meridian-channel", &channel]).unwrap(),
|
||||
])
|
||||
.sign_with_keys(&owner)
|
||||
|
|
@ -620,6 +621,7 @@ async fn git_pointer_rollback_is_quarantined_for_read_and_write() {
|
|||
Tag::parse(["d", &repo]).unwrap(),
|
||||
Tag::parse(["name", "rollback quarantine fixture"]).unwrap(),
|
||||
Tag::parse(["buzz-channel", &channel]).unwrap(),
|
||||
Tag::parse(["codebase-chat-channel", &channel]).unwrap(),
|
||||
Tag::parse(["meridian-channel", &channel]).unwrap(),
|
||||
])
|
||||
.sign_with_keys(&owner)
|
||||
|
|
@ -689,6 +691,7 @@ async fn git_concurrent_push_one_wins_and_repo_recovers() {
|
|||
Tag::parse(["d", &repo]).unwrap(),
|
||||
Tag::parse(["name", "e2e concurrent git repo"]).unwrap(),
|
||||
Tag::parse(["buzz-channel", &channel]).unwrap(),
|
||||
Tag::parse(["codebase-chat-channel", &channel]).unwrap(),
|
||||
Tag::parse(["meridian-channel", &channel]).unwrap(),
|
||||
])
|
||||
.sign_with_keys(&owner)
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ default so long-lived WebSocket connections have time to drain.
|
|||
Enable `serviceMonitor.enabled` and `prometheusRule.enabled` to scrape relay
|
||||
metrics and install the bundled availability, dependency, and correctness
|
||||
alerts. Every alert links to `docs/runbooks/relay-alerts.md`. The rule pack
|
||||
keeps `buzz_*` fallbacks beside renamed `meridian_*` metrics for one
|
||||
keeps `codebase_chat_*` fallbacks beside renamed `meridian_*` metrics for one
|
||||
retention window so a rolling rename does not create an observability blackout.
|
||||
|
||||
The readiness endpoint requires Postgres, a pooled Redis checkout, and all
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ spec:
|
|||
> on (namespace) sum by (namespace) (max by (namespace, pod) (up{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}} == bool 1))
|
||||
or (max by (namespace, pod) (up{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}} == 1)
|
||||
unless on (namespace, pod) max by (namespace, pod) (meridian_relay_ready{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}
|
||||
or buzz_relay_ready{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}})))
|
||||
or codebase_chat_relay_ready{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}})))
|
||||
for: 5m
|
||||
labels: { severity: page, owner: meridian-relay }
|
||||
annotations:
|
||||
|
|
@ -43,7 +43,7 @@ spec:
|
|||
description: Prometheus has no kube-state-metrics replica inventory for the relay deployment, so a completely undiscovered replica cannot be distinguished from healthy capacity.
|
||||
runbook_url: {{ .Values.prometheusRule.runbookUrl | quote }}
|
||||
- alert: MeridianRelayNotReady
|
||||
expr: max by (namespace, pod) (meridian_relay_ready{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}} == 0 or buzz_relay_ready{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}} == 0) > 0
|
||||
expr: max by (namespace, pod) (meridian_relay_ready{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}} == 0 or codebase_chat_relay_ready{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}} == 0) > 0
|
||||
for: 2m
|
||||
labels: { severity: page, owner: meridian-relay }
|
||||
annotations:
|
||||
|
|
@ -69,7 +69,7 @@ spec:
|
|||
- name: meridian-relay.dependencies
|
||||
rules:
|
||||
- alert: MeridianDatabasePoolSaturated
|
||||
expr: (meridian_db_pool_active{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}} / clamp_min(meridian_db_pool_max{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}, 1) or buzz_db_pool_active{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}} / clamp_min(buzz_db_pool_max{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}, 1)) > 0.9
|
||||
expr: (meridian_db_pool_active{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}} / clamp_min(meridian_db_pool_max{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}, 1) or codebase_chat_db_pool_active{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}} / clamp_min(codebase_chat_db_pool_max{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}, 1)) > 0.9
|
||||
for: 10m
|
||||
labels: { severity: warning, owner: meridian-relay }
|
||||
annotations:
|
||||
|
|
@ -77,7 +77,7 @@ spec:
|
|||
description: More than 90 percent of writer connections have been active for ten minutes; inspect slow queries before raising the pool ceiling.
|
||||
runbook_url: {{ .Values.prometheusRule.runbookUrl | quote }}
|
||||
- alert: MeridianReplicaFenceClosed
|
||||
expr: max by (namespace, pod) (meridian_db_replica_fence_open{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}} or buzz_db_replica_fence_open{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}) == 0 and on (namespace, pod) max by (namespace, pod) (meridian_db_read_pool_max{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}} or buzz_db_read_pool_max{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}) > 0
|
||||
expr: max by (namespace, pod) (meridian_db_replica_fence_open{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}} or codebase_chat_db_replica_fence_open{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}) == 0 and on (namespace, pod) max by (namespace, pod) (meridian_db_read_pool_max{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}} or codebase_chat_db_read_pool_max{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}) > 0
|
||||
for: 5m
|
||||
labels: { severity: warning, owner: meridian-relay }
|
||||
annotations:
|
||||
|
|
@ -85,7 +85,7 @@ spec:
|
|||
description: Replica reads have remained unsafe for five minutes and traffic is pinned to the writer.
|
||||
runbook_url: {{ .Values.prometheusRule.runbookUrl | quote }}
|
||||
- alert: MeridianStorageSweepFailed
|
||||
expr: max by (namespace, pod) (meridian_storage_sweep_ok{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}} or buzz_storage_sweep_ok{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}) == 0
|
||||
expr: max by (namespace, pod) (meridian_storage_sweep_ok{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}} or codebase_chat_storage_sweep_ok{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}) == 0
|
||||
for: 20m
|
||||
labels: { severity: warning, owner: meridian-relay }
|
||||
annotations:
|
||||
|
|
@ -95,7 +95,7 @@ spec:
|
|||
- name: meridian-relay.correctness
|
||||
rules:
|
||||
- alert: MeridianAuditWriteErrors
|
||||
expr: increase(meridian_audit_log_errors_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}[10m]) > 0 or increase(meridian_audit_send_errors_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}[10m]) > 0 or increase(buzz_audit_log_errors_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}[10m]) > 0 or increase(buzz_audit_send_errors_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}[10m]) > 0
|
||||
expr: increase(meridian_audit_log_errors_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}[10m]) > 0 or increase(meridian_audit_send_errors_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}[10m]) > 0 or increase(codebase_chat_audit_log_errors_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}[10m]) > 0 or increase(codebase_chat_audit_send_errors_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}[10m]) > 0
|
||||
for: 0m
|
||||
labels: { severity: page, owner: meridian-relay }
|
||||
annotations:
|
||||
|
|
@ -103,7 +103,7 @@ spec:
|
|||
description: Any audit enqueue or durable-chain write error is a correctness incident and pages immediately.
|
||||
runbook_url: {{ .Values.prometheusRule.runbookUrl | quote }}
|
||||
- alert: MeridianPostCommitDispatchErrors
|
||||
expr: increase(meridian_post_commit_dispatch_errors_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}[10m]) > 0 or increase(buzz_post_commit_dispatch_errors_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}[10m]) > 0
|
||||
expr: increase(meridian_post_commit_dispatch_errors_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}[10m]) > 0 or increase(codebase_chat_post_commit_dispatch_errors_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}[10m]) > 0
|
||||
for: 0m
|
||||
labels: { severity: page, owner: meridian-relay }
|
||||
annotations:
|
||||
|
|
@ -111,7 +111,7 @@ spec:
|
|||
description: A durable event was accepted but at least one fan-out or side-effect stage failed.
|
||||
runbook_url: {{ .Values.prometheusRule.runbookUrl | quote }}
|
||||
- alert: MeridianWorkflowFailures
|
||||
expr: sum(increase(meridian_workflow_runs_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }},status="failed"}[15m])) > 5 or sum(increase(buzz_workflow_runs_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }},status="failed"}[15m])) > 5
|
||||
expr: sum(increase(meridian_workflow_runs_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }},status="failed"}[15m])) > 5 or sum(increase(codebase_chat_workflow_runs_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }},status="failed"}[15m])) > 5
|
||||
for: 5m
|
||||
labels: { severity: warning, owner: meridian-relay }
|
||||
annotations:
|
||||
|
|
@ -119,7 +119,7 @@ spec:
|
|||
description: More than five workflow failures in fifteen minutes suggests a dependency, definition, or secret-resolution regression.
|
||||
runbook_url: {{ .Values.prometheusRule.runbookUrl | quote }}
|
||||
- alert: MeridianWebSocketBackpressureDisconnects
|
||||
expr: increase(meridian_ws_backpressure_disconnects_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}[10m]) > 25 or increase(buzz_ws_backpressure_disconnects_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}[10m]) > 25
|
||||
expr: increase(meridian_ws_backpressure_disconnects_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}[10m]) > 25 or increase(codebase_chat_ws_backpressure_disconnects_total{namespace={{ $namespace | quote }},pod=~{{ $podPattern | quote }}}[10m]) > 25
|
||||
for: 5m
|
||||
labels: { severity: warning, owner: meridian-relay }
|
||||
annotations:
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ PROMETHEUS_PORT=9090
|
|||
# _sqlx_migrations histories and corrupts both.
|
||||
MERIDIAN_CONTROL_DB=meridian_control_plane
|
||||
MERIDIAN_CONTROL_PUBLIC_ORIGIN=https://register.meridian.r2d2.office.ilab.zone
|
||||
MERIDIAN_CONTROL_API_BASE_PATH=/api/codebase
|
||||
MERIDIAN_CONTROL_API_BASE_PATH=/api/meridian
|
||||
MERIDIAN_CONTROL_COMMUNITY_HOST_SUFFIX=communities.meridian.r2d2.office.ilab.zone
|
||||
MERIDIAN_CONTROL_RELAY_SCHEME=wss
|
||||
MERIDIAN_CONTROL_COMMUNITY_LIMIT=3
|
||||
|
|
@ -84,7 +84,7 @@ MERIDIAN_CONTROL_IDENTITY_PROVIDER=oidc
|
|||
MERIDIAN_RELAY_HOST=relay.meridian.r2d2.office.ilab.zone
|
||||
MERIDIAN_CONTROL_HOST=register.meridian.r2d2.office.ilab.zone
|
||||
MERIDIAN_COMMUNITY_HOST_SUFFIX=communities.meridian.r2d2.office.ilab.zone
|
||||
MERIDIAN_COMMUNITY_HOST_SUFFIX_RE=communities\.codebase\.design
|
||||
MERIDIAN_COMMUNITY_HOST_SUFFIX_RE=communities\.meridian\.r2d2\.office\.ilab\.zone
|
||||
|
||||
# Must be a DNS-01 resolver: community hosts are minted under a wildcard, and
|
||||
# Let's Encrypt will not issue *.communities.… over HTTP-01.
|
||||
|
|
|
|||
|
|
@ -38,24 +38,20 @@ CTX="$(kubectl config current-context)"
|
|||
log "context: $CTX"; kubectl get nodes | tee "$EVID/nodes.txt"
|
||||
|
||||
# ── 1. corporate-proxy CA + npm mirror (TLS-intercepting gateway) ────────────
|
||||
# Two stacked blocks on Block's network: (a) the gateway re-signs TLS with
|
||||
# internal CAs the build container doesn't trust; (b) public registry.npmjs.org
|
||||
# is policy-blocked (Dependency Confusion mitigation), so npm/corepack must use
|
||||
# the Artifactory mirror. Both no-op on a normal network (build-args stay unset).
|
||||
# Two independent escape hatches for a restricted corporate network: (a) a
|
||||
# TLS-intercepting gateway re-signs certificates with an internal CA the build
|
||||
# container does not trust; (b) the public npm registry is policy-blocked, so
|
||||
# npm/corepack must use an internal mirror. Both no-op on a normal network —
|
||||
# the build-args stay unset and nothing below changes.
|
||||
CA_ARG=()
|
||||
REG_ARG=()
|
||||
# (a) Build a complete internal-CA bundle from the macOS System keychain.
|
||||
if [ ! -f "$CA_PEM" ] && command -v security >/dev/null 2>&1; then
|
||||
log "exporting Block internal CA bundle from System keychain"
|
||||
: > "$CA_PEM"
|
||||
for name in "Cloudflare Gateway CA" \
|
||||
"Service To Service AWS Native CA production G0" \
|
||||
"Corp Systems AWS Native CA production G0" \
|
||||
"Block, Inc CA G1" \
|
||||
"Square Primary Certificate Authority - G2"; do
|
||||
security find-certificate -a -c "$name" -p /Library/Keychains/System.keychain >> "$CA_PEM" 2>/dev/null || true
|
||||
done
|
||||
fi
|
||||
# (a) Supply your own CA bundle if your network intercepts TLS: concatenate the
|
||||
# PEM-encoded internal CAs into `deploy/local/proxy-ca.pem` and re-run. On
|
||||
# macOS that is roughly:
|
||||
# security find-certificate -a -c "<CA name>" -p /Library/Keychains/System.keychain \
|
||||
# >> deploy/local/proxy-ca.pem
|
||||
# (The previous automatic export was keyed to Block's corporate CA names and
|
||||
# does not apply to a self-hosted deployment.)
|
||||
if [ -f "$CA_PEM" ] && grep -q 'BEGIN CERTIFICATE' "$CA_PEM"; then
|
||||
CA_ARG=(--build-arg "EXTRA_CA_CERTS=deploy/local/proxy-ca.pem")
|
||||
log "using proxy CA bundle ($(grep -c 'BEGIN CERTIFICATE' "$CA_PEM") certs)"
|
||||
|
|
|
|||
|
|
@ -349,14 +349,14 @@ function maybeEnableMeridianTranslucent(
|
|||
* continuation can't re-enable translucency after a newer theme superseded it.
|
||||
*/
|
||||
async function applyMeridianVibrancy(themeName: string) {
|
||||
const codebaseChat = isMeridianTheme(themeName);
|
||||
const meridianTheme = isMeridianTheme(themeName);
|
||||
const requestToken = ++meridianVibrancyRequest;
|
||||
|
||||
// Meridian Light and Meridian Dark use the same native material. Rebuilding the
|
||||
// NSVisualEffectView on every mode change briefly clears the layer behind
|
||||
// the webview and makes the new CSS theme appear late. Keep the installed
|
||||
// layer and let applyTheme swap only the color tokens.
|
||||
if (codebaseChat && meridianVibrancyEnabled && meridianVibrancyReady) {
|
||||
if (meridianTheme && meridianVibrancyEnabled && meridianVibrancyReady) {
|
||||
maybeEnableMeridianTranslucent(themeName, requestToken);
|
||||
return;
|
||||
}
|
||||
|
|
@ -374,18 +374,18 @@ async function applyMeridianVibrancy(themeName: string) {
|
|||
|
||||
try {
|
||||
await invokeTauri<void>("set_window_vibrancy", {
|
||||
enabled: codebaseChat,
|
||||
enabled: meridianTheme,
|
||||
material: MERIDIAN_VIBRANCY_MATERIAL,
|
||||
});
|
||||
// A newer theme change superseded this request while the IPC was in flight;
|
||||
// that later call owns the current translucency state, so don't clobber it.
|
||||
if (requestToken !== meridianVibrancyRequest) return;
|
||||
meridianVibrancyEnabled = codebaseChat;
|
||||
meridianVibrancyEnabled = meridianTheme;
|
||||
// Native layer is installed. Record readiness and try to enable translucency
|
||||
// — but only if `applyMeridianSidebar` has already installed the Meridian gradient
|
||||
// vars. If that effect hasn't landed yet (the IPC won the race), it will
|
||||
// call maybeEnableMeridianTranslucent itself once the marker is applied.
|
||||
if (codebaseChat && isMacPlatform()) {
|
||||
if (meridianTheme && isMacPlatform()) {
|
||||
meridianVibrancyReady = true;
|
||||
maybeEnableMeridianTranslucent(themeName, requestToken);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>com.meridian.deeplink</string>
|
||||
<string>zone.ilab.office.r2d2.meridian.deeplink</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>meridian</string>
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ void main() {
|
|||
});
|
||||
|
||||
test('borrow the GitHub palettes', () {
|
||||
final codebaseChat = findTheme(meridianThemeName)!;
|
||||
final meridianLight = findTheme(meridianThemeName)!;
|
||||
final github = findTheme('github-light')!;
|
||||
expect(codebaseChat.bg, github.bg);
|
||||
expect(codebaseChat.fg, github.fg);
|
||||
expect(codebaseChat.comment, github.comment);
|
||||
expect(meridianLight.bg, github.bg);
|
||||
expect(meridianLight.fg, github.fg);
|
||||
expect(meridianLight.comment, github.comment);
|
||||
|
||||
final meridianDark = findTheme(meridianDarkThemeName)!;
|
||||
final githubDark = findTheme('github-dark')!;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue