Skip to content

Enforce project-channel webhook routing - #33

Merged
kevinle128 merged 14 commits into
mainfrom
archon/thread-a187515d
Aug 21, 2026
Merged

kevinle128 merged 14 commits into
mainfrom
archon/thread-a187515d

Conversation

@kevinle128

Copy link
Copy Markdown
Owner

Summary

Adds project-channel webhook routing for workflows and hardens relay admission around repository/project authority. The change introduces routing schema support, idempotent workflow admission storage, live repository/project head lookups, route revalidation, and E2E coverage for static compatibility plus project-channel webhook routing.

Key changes:

  • Add workflow routing schema and executor plumbing in crates/buzz-workflow.
  • Add database support for latest live repository/project heads and idempotent workflow admission.
  • Add relay workflow admission and route handling that resolves repository identity, validates project claims, rejects invalid aliases, and activates revalidated routes.
  • Add migration 0032_workflow_run_route_idempotency.sql and update schema metadata.
  • Add E2E coverage in crates/buzz-test-client/tests/e2e_workflow_project_channel_routing.rs.

Related issue

No linked GitHub issue found. Duplicate PR search for Fixes #187515 OR Closes #187515 returned none.

Testing

Not rerun during PR creation. Branch commits include fixes for workflow routing tests, migration expectations, and the workflow routing clippy gate.

Run: aece743d73b0fa09a2091e5e94b9dc9c
Epoch: 0
Node: review-fix-plan
Signed-off-by: dale <9694366+anhle128@users.noreply.github.com>
Run: aece743d73b0fa09a2091e5e94b9dc9c
Epoch: 0
Node: implement
Signed-off-by: dale <9694366+anhle128@users.noreply.github.com>
Signed-off-by: dale <9694366+anhle128@users.noreply.github.com>
Signed-off-by: dale <9694366+anhle128@users.noreply.github.com>
Signed-off-by: dale <9694366+anhle128@users.noreply.github.com>
Signed-off-by: dale <9694366+anhle128@users.noreply.github.com>
Signed-off-by: dale <9694366+anhle128@users.noreply.github.com>
… live

Signed-off-by: dale <9694366+anhle128@users.noreply.github.com>
Signed-off-by: dale <9694366+anhle128@users.noreply.github.com>
Signed-off-by: dale <9694366+anhle128@users.noreply.github.com>
…k routing

Signed-off-by: dale <9694366+anhle128@users.noreply.github.com>
Signed-off-by: dale <9694366+anhle128@users.noreply.github.com>
Signed-off-by: dale <9694366+anhle128@users.noreply.github.com>
Signed-off-by: dale <9694366+anhle128@users.noreply.github.com>
@kevinle128
kevinle128 merged commit 8b57c46 into main Aug 21, 2026
25 of 31 checks passed
kevinle128 pushed a commit that referenced this pull request Sep 10, 2026
## Why

Database pressure currently collapses several distinct delays into one
symptom. This adds the evidence layer needed to distinguish pool
acquisition wait, logical database operation time, advisory-lock wait,
and selected transaction duration before changing timeout or retry
policy.

This is the phase 2 Lane A observability bundle for
[#26](TheSentinel454#26),
[#28](TheSentinel454#28), and
[#33](TheSentinel454#33). It is stacked
on block#6668.

## What

- Record explicit reader/writer checkout wait and acquisition outcomes
with `buzz_db_pool_acquire_wait_seconds` and
`buzz_db_pool_acquisitions_total`.
- Extend the compile-time `#[datastore_span(name = "...")]` seam with
`buzz_db_operation_duration_seconds`, so operation labels remain static
source literals instead of request data.
- Route correctness-critical replacement, membership, push-gate,
deletion, and migration/schema-safety advisory locks through one
observer without changing their SQL, order, scope, or blocking behavior.
- Measure six internally owned transaction lifetimes with
`buzz_db_transaction_duration_seconds`, starting after `BEGIN` succeeds
and ending after explicit commit/rollback or scope exit.
- Emit root slow-operation warnings at 500 ms, logging the first slow
completion and then 1/100 per call site with only `operation`,
`outcome`, and `elapsed_ms`.
- Document names, units, fixed label vocabularies, measurement
boundaries, and blind spots in this PR description.

Fixed labels are deliberately small:

- `pool_role`: `writer`, `reader`
- `lock_type`: `replacement`, `membership`, `push_gate`, `deletion`,
`migration_schema_safety`
- `outcome`: `success`, `error`, `timeout` where SQLx/PostgreSQL can
distinguish it accurately
- `operation`: compile-time datastore names plus the six closed
transaction operation names documented in the runbook

No metric or slow warning contains community IDs, event IDs, event
kinds, coordinates, d-tags, SQL/query text, query IDs, returned errors,
or event content.

## Coverage boundaries

- Operation duration is the complete annotated logical function body,
not pure SQL execution; it may include implicit checkout, lock wait,
nested operations, and application work. Cancelled futures do not reach
its completion hook.
- Pool timing covers explicit helper checkouts, including proved-reader
routing and selected writer-owned transactions. Implicit SQLx checkout
through `&PgPool` remains folded into operation duration.
- Lock timing covers application-side blocking locks in the five named
families. Trigger/stored-procedure locks, channel-TTL locking, the usage
try-lock, and the audit service session lock remain outside this slice.
- Transaction timing covers only the six wholly owned boundaries
documented in the runbook. It excludes pool wait, `BEGIN`, asynchronous
rollback cleanup after an early return, and caller-owned
`Db::begin_transaction` lifetime.

## Relationship to block#6229

block#6229 is the incident-driven timeout precursor. This PR does not add or
change `statement_timeout`, `lock_timeout`,
`idle_in_transaction_session_timeout`, retries, audit durability, or
client-visible conflicts. It provides the missing distributions needed
to evaluate those policies later and intentionally leaves block#6229's open
audit retry/durability finding untouched.

The branches overlap in `crates/buzz-db/src/lib.rs` and
`crates/buzz-db/src/migration.rs`, so a later rebase may need textual
conflict resolution, but the behavior is complementary rather than
duplicated.

## Risk assessment

Moderate-low. The primary risk is instrumentation overhead and added
static series. Cardinality is source-bounded, slow logs are
sampled/redacted root events, and the lock/transaction changes wrap
existing awaits without changing policy or ordering.

## Verification

Author workstation: `buzz-tornquist-db-pressure-observability`
(`2010927`), exact head `d7cf833e26c528adfcde3917ded80daf6f4ddac9`,
parent `6f50e6b2b2a996349149af61d35bdd6a355f77fd`.

- `cargo fmt --all --check` — passed
- `cargo clippy -p buzz-datastore-tracing -p buzz-db -p buzz-audit -p
buzz-search -p buzz-relay --all-targets -- -D warnings` — passed
- `cargo test -p buzz-datastore-tracing --quiet` — 4 passed
- `cargo test -p buzz-db --quiet` — 109 passed, 200 ignored
- `cargo test -p buzz-audit -p buzz-search --quiet` — 16 passed, 25
ignored
- `cargo test -p buzz-relay --lib --quiet -- --test-threads=1` — 906
passed, 48 ignored
- Native PostgreSQL focused tests for pool success/timeout/error, lock
success/contention/timeout/error, replacement, membership serialization,
push ordering, deletion fencing, migration/schema exclusion, and reader
fallback — 8 passed

The default-parallel relay run passed once; subsequent runs exposed the
existing load-sensitive
`api::mesh_demo::tests::demo_join_forwarded_arm_round_trips_echo` 504 at
the end of the suite. That test passes in isolation and the full relay
suite passes serially.

Independent exact-head review workstation:
`buzz-tornquist-db-pressure-observability-review` (`2013067`).
Formatting, the same all-target clippy command, datastore
instrumentation tests, DB unit tests, source privacy guards, and
diff/non-goal audits passed; no review findings.

Generated with Codex

---------

Signed-off-by: tornquist <tornquist@squareup.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant