Skip to content

fix(hub): dedupe channel SystemEvents on dedupe_key before INSERT - #132

Open
heavygee wants to merge 4 commits into
feat/contrib-state-channel-ingestfrom
fix/system-event-dedupe-key
Open

fix(hub): dedupe channel SystemEvents on dedupe_key before INSERT#132
heavygee wants to merge 4 commits into
feat/contrib-state-channel-ingestfrom
fix/system-event-dedupe-key

Conversation

@heavygee

@heavygee heavygee commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Summary

Channel POST /api/system-events returned 500 when a producer re-emitted with the same dedupeKey but a different idempotencyKey (SQLite UNIQUE constraint failed: events.dedupe_key). Exit-reflection emit helpers use stable dedupeKey (exit-reflection:<session>:<pr|0>) and vary idempotencyKey with a hash of skip/reason text.

Mirrors idempotency handling: lookup dedupe_key before INSERT in insertSystemEvent, expose getByDedupeKey on the event store, and check in insertChannelSystemEvent so the route returns 200 with deduped: true without re-promoting inbox.

Test plan

  • bun test hub/src/web/routes/systemEvents.test.ts (regression: same dedupeKey, different idempotencyKey)

Issues

Fixes tiann#1624

Upstream handoff

Stacked on feat/contrib-state-channel-ingest (1 commit, 4 files). Meta: open cross-repo PR to tiann/hapi when channel ingest lands (Lane A prepare-only).

@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

'SELECT * FROM overseer_events WHERE dedupe_key = ? LIMIT 1'

P1 Badge Query the actual events table for dedupe keys

The new lookup targets overseer_events, but ensureOverseerEventsSchema creates only the events table and no view or alias named overseer_events exists anywhere in the repository. Whenever an insert supplies dedupeKey, this pre-insert lookup therefore throws no such table: overseer_events, causing channel POSTs to return 500 instead of inserting or deduplicating the event; query events here as the idempotency lookup does.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@heavygee
heavygee force-pushed the fix/system-event-dedupe-key branch from 6436129 to 9bf65a7 Compare August 17, 2026 19:07

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9bf65a757d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hub/src/sync/syncEngine.ts Outdated
heavygee and others added 2 commits August 17, 2026 20:06
insertSystemEvent and insertChannelSystemEvent only checked idempotency_key.
Re-emits with the same dedupeKey but a different idempotencyKey (e.g.
exit-reflection skip reason drift) hit UNIQUE on overseer_events.dedupe_key
and returned HTTP 500.

Lookup dedupe_key like idempotency and return the existing row as deduped.

Fixes tiann#1624

Co-authored-by: Cursor <cursoragent@cursor.com>
Persist namespace on events rows, replace global dedupe_key unique index
with (namespace, dedupe_key), and pass request namespace through channel
ingest so cross-tenant dedupe keys cannot collide.

Closes tiann#1624 (partial — stacked on contrib-state ingest).

Co-authored-by: Cursor <cursoragent@cursor.com>
@heavygee
heavygee force-pushed the fix/system-event-dedupe-key branch from 9bf65a7 to 9d91e5a Compare August 17, 2026 20:08
@heavygee

Copy link
Copy Markdown
Owner Author

Meta ping response — CI + P1 thread addressed @ 9d91e5ac1

CI fix (base heal 52c2f0e21 on feat/contrib-state-channel-ingest): stub EventsDebugControls / InboxDebugControls in settings/index.test.tsx — About route mounts Overseer debug panels that require AppContext; suite only asserts metadata (same pattern as driver).

P1 namespace dedupe (9d91e5ac1):

  • Persist namespace on events rows (additive column + migration in ensureOverseerEventsSchema)
  • Replace global dedupe_key unique index with (namespace, dedupe_key)
  • Pass request namespace through insertChannelSystemEvent + scoped lookup
  • Regression test: same dedupeKey in two namespaces inserts two rows

Verification: bun typecheck clean; hub suite 556 pass (incl. 14 systemEvents tests).

Lane A: still parked until contrib-state channel ingest lands on tiann/hapi:main; then cherry-pick stack to upstream PR closing tiann#1624.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9d91e5ac17

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hub/src/store/events.ts Outdated
Legacy DBs with pre-namespace events tables failed Store init because the
composite dedupe index ran before ensureEventsNamespaceColumn could ALTER.

Co-authored-by: Cursor <cursoragent@cursor.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3353ee0a44

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hub/src/store/events.ts
Legacy channel events linked to non-default sessions were left at namespace
'default' after ALTER, breaking namespaced dedupe replay. Copy namespace from
sessions.namespace for rows with related_session_id before creating the
composite dedupe index.

Co-authored-by: Cursor <cursoragent@cursor.com>
@heavygee heavygee added cold-review-clean Fork-side bot review is satisfactory; safe to promote to upstream PR and removed cold-review-clean Fork-side bot review is satisfactory; safe to promote to upstream PR labels Aug 17, 2026
heavygee added a commit that referenced this pull request Aug 24, 2026
…fier

cold-review-clean now passes the CI dimension when gh returns an empty
check rollup or transport failure (GH 503), matching the existing bot
override. Meta classifier treats CRC + merge-clean + no rollup as ✅
instead of ⚠️ / "push to trigger bot review".

Refs tiann#1624 flake noise on #91/#132.

Co-authored-by: Cursor <cursoragent@cursor.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