Add shared transactional outbox persistence#155
Conversation
…to codex/ws-con-001-02a-shared-outbox-persistence
…to codex/ws-con-001-02a-shared-outbox-persistence
…to codex/ws-con-001-02a-shared-outbox-persistence
…to codex/ws-con-001-02a-shared-outbox-persistence
…to codex/ws-con-001-02a-shared-outbox-persistence
…to codex/ws-con-001-02a-shared-outbox-persistence
…to codex/ws-con-001-02a-shared-outbox-persistence
…to codex/ws-con-001-02a-shared-outbox-persistence
📝 WalkthroughWalkthroughThis PR reconciles the WS-CON-001 trusted baseline and implements CON-02A shared transactional outbox persistence. It adds strict payload validation, PostgreSQL schema custody, caller-owned transactional append/replay behavior, migration safeguards, concurrency handling, and focused verification documentation and tests. ChangesCON-02A shared transactional outbox
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant OutboxService
participant OutboxRepository
participant PostgreSQL
Caller->>OutboxService: append validated event
OutboxService->>OutboxRepository: reserve event and payload digest
OutboxRepository->>PostgreSQL: insert, flush, lock conflicts
PostgreSQL-->>OutboxRepository: created or existing event
OutboxRepository-->>OutboxService: reservation result
OutboxService-->>Caller: CREATED, REPLAYED, or conflict
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
backend/alembic/versions/0027_shared_transactional_outbox.py (1)
176-184: 🧹 Nitpick | 🔵 TrivialPlan a retention/purge path before production load.
ix_outbox_events_retentionandarchived_atestablish the retention surface, but nothing in v0.1 archives or purges terminal rows, sooutbox_eventsgrows unbounded as delivery volume accumulates. This is out of scope for 02A (dispatch/retention is later work), but ensure a background archival/purge job — coordinated with the custody triggers via the disable/enable pattern already used in tests — lands before this reaches sustained traffic.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/alembic/versions/0027_shared_transactional_outbox.py` around lines 176 - 184, Plan and implement a background archival/purge job for terminal outbox rows using ix_outbox_events_retention and archived_at, so outbox_events does not grow without bound under sustained traffic. Coordinate archival and deletion with the custody triggers using the existing disable/enable pattern from the tests, and ensure this retention path lands before production load while keeping the current migration scope unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
@.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/chunks/WS-CON-001-02A-shared-outbox-persistence.md:
- Around line 38-58: Add an explicit required-reviewers section to the
“Verification and reviewers” content, naming the reviewer roles or identities
required before implementation begins. Keep the existing verification commands
and acceptance criteria unchanged, and ensure the section clearly identifies
reviewer requirements alongside the other chunk prerequisites.
In
@.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/DISCOVERY.md:
- Around line 179-186: Reconcile the AUTH catalogue count terminology across
DISCOVERY.md and the referenced PLAN.md, SOURCE_MANIFEST.md, and STATUS.md
materials: replace or explicitly mark the stale “15 active” and “50 planned”
observation so the baseline consistently uses the established 17/48 counts.
Preserve the existing 74/65/17/48 breakdown and align wording with README.md,
docs/glossary.md, and docs/architecture_lockdown.md.
- Line 159: Reconcile all REV lifecycle-gate terminology so every durable record
uses the authoritative REV-12A1/12A3 sequence, with REV-12A3 retained as the
drain-observation prerequisite and any REV-12A parent/child alias explicitly
defined. Update
.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/DISCOVERY.md
lines 159 and 223, align the shared-fence hook naming in
JOINT_RELEASE_HANDOFF.md lines 115-118, and update the rollout gate in STATUS.md
lines 172-173; keep terminology consistent with README.md, docs/glossary.md, and
docs/architecture_lockdown.md.
In
@.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/JOINT_RELEASE_HANDOFF.md:
- Around line 157-159: Update the release-ownership wording in the planning
documents so it matches the handoff’s designation of REV-13C as the sole public
product release owner, or explicitly define REV-13 as its parent initiative.
Keep terminology consistent with README.md, docs/glossary.md, and
docs/architecture_lockdown.md, and ensure ownership is unambiguous.
In
@.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/SOURCE_MANIFEST.md:
- Around line 45-52: Update the later runtime-observation text in
SOURCE_MANIFEST.md to refer to REV-04B instead of REV-04, keeping the
FinalAcceptance prerequisite identifier consistent with the existing normative
description and repository terminology.
---
Nitpick comments:
In `@backend/alembic/versions/0027_shared_transactional_outbox.py`:
- Around line 176-184: Plan and implement a background archival/purge job for
terminal outbox rows using ix_outbox_events_retention and archived_at, so
outbox_events does not grow without bound under sustained traffic. Coordinate
archival and deletion with the custody triggers using the existing
disable/enable pattern from the tests, and ensure this retention path lands
before production load while keeping the current migration scope unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 8be695bd-33ce-4847-8bf1-905a130804ec
📒 Files selected for processing (27)
.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/ACTIVE_DOC_INVENTORY.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/AUTHORIZATION_HANDOFF.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/CHUNK_MAP.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/DECISIONS.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/DISCOVERY.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/INTENT.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/JOINT_RELEASE_HANDOFF.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/PLAN.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/RUNTIME_VERIFICATION.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/SOURCE_MANIFEST.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/STATUS.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/chunks/WS-CON-001-02A-shared-outbox-persistence.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/reviews/WS-CON-001-02A-internal-review-evidence.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/reviews/WS-CON-001-02A-pr-trust-bundle.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/reviews/WS-CON-001-02A-preimplementation-plan-review.md.agent-loop/merge-intents/WS-CON-001-02A.jsonbackend/alembic/versions/0027_shared_transactional_outbox.pybackend/app/db/models.pybackend/app/modules/outbox/__init__.pybackend/app/modules/outbox/models.pybackend/app/modules/outbox/repository.pybackend/app/modules/outbox/schemas.pybackend/app/modules/outbox/service.pybackend/tests/assertion_helpers.pybackend/tests/test_alembic.pybackend/tests/test_assertion_helpers.pybackend/tests/test_outbox.py
| CON-11 publishes the hidden dependency manifest but registers no route. | ||
| REV-13A consumes it in preflight and REV-13C owns the sole public product | ||
| release and final HTTP proof. This handoff starts no chunk automatically. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Synchronize the final release owner across planning documents.
This handoff now identifies REV-13C as the sole public release owner, while PLAN.md still says REV-13 owns final public release. Update the companion wording or explicitly define REV-13 as the parent so release ownership is unambiguous.
As per coding guidelines, keep terminology consistent with README.md, docs/glossary.md, and docs/architecture_lockdown.md.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
@.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/JOINT_RELEASE_HANDOFF.md
around lines 157 - 159, Update the release-ownership wording in the planning
documents so it matches the handoff’s designation of REV-13C as the sole public
product release owner, or explicitly define REV-13 as its parent initiative.
Keep terminology consistent with README.md, docs/glossary.md, and
docs/architecture_lockdown.md, and ensure ownership is unambiguous.
Source: Coding guidelines
…shared-outbox-persistence
…shared-outbox-persistence
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/reviews/WS-CON-001-02A-preimplementation-plan-review.md (1)
120-131: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winKeep the active migration lineage consistent with the shipped PR.
These review-plan passages still identify CON’s migration as
0028_shared_transactional_outbox, but the current lineage is0028_artifact_admission→0029_shared_transactional_outbox:
.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/reviews/WS-CON-001-02A-preimplementation-plan-review.md#L120-L131: update the implementation target or label it historical..agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/reviews/WS-CON-001-02A-preimplementation-plan-review.md#L355-L362: update the closing reconciliation or label it superseded evidence.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/reviews/WS-CON-001-02A-preimplementation-plan-review.md around lines 120 - 131, Update the implementation target in .agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/reviews/WS-CON-001-02A-preimplementation-plan-review.md lines 120-131 to use the active 0028_artifact_admission → 0029_shared_transactional_outbox lineage, or explicitly label the 0028_shared_transactional_outbox reference as historical. Apply the same update or superseded-evidence label to the closing reconciliation at lines 355-362.
🧹 Nitpick comments (1)
backend/tests/test_alembic.py (1)
122-219: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low valueSolid concurrency/schema contract test — schema/index/trigger assertions cross-checked cleanly against the migration.
One minor robustness note: the
await asyncio.sleep(0.1)followed byassert not downgrade.done()(used inside_outbox_downgrade_writer_race, exercised here) is a fixed-timing assumption about how fast the downgrade thread reaches theLOCK TABLE ... ACCESS EXCLUSIVEstatement. Under CI contention this could theoretically flake. A polling loop (e.g., pollpg_locksor retry with backoff) would be more robust than a fixed sleep, though the current approach is a common and generally acceptable pattern for this kind of test.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/tests/test_alembic.py` around lines 122 - 219, Improve the synchronization in _outbox_downgrade_writer_race by replacing the fixed asyncio.sleep(0.1) and immediate downgrade.done() assertion with polling, such as checking pg_locks or retrying with bounded backoff, until the downgrade reaches the expected lock-wait state. Preserve the existing concurrency assertions and ensure the test fails clearly if the state is not reached within a timeout.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
@.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/AUTHORIZATION_HANDOFF.md:
- Around line 8-9: Prevent wrapped PR references from being parsed as Markdown
headings by keeping each PR reference inline with its preceding text or escaping
the leading hash. Update AUTHORIZATION_HANDOFF.md lines 8-9 to keep PR `#139`
inline, DECISIONS.md lines 225-226 to keep PR `#146` and PR `#153` inline, STATUS.md
line 55 to keep PR `#153` inline, and STATUS.md line 69 to keep PR `#156` inline.
In
@.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/INTENT.md:
- Around line 13-19: Update the active trusted-main baseline from 8d5eb15b to
3b1d6379 and refresh the merged-PR list in INTENT.md lines 13-19; update the
proposed-approach baseline in PLAN.md lines 5-10 and the authorization-boundary
baseline in PLAN.md lines 167-184. Keep all three sites aligned, or explicitly
mark them historical if they must retain the prior SHA.
---
Outside diff comments:
In
@.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/reviews/WS-CON-001-02A-preimplementation-plan-review.md:
- Around line 120-131: Update the implementation target in
.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/reviews/WS-CON-001-02A-preimplementation-plan-review.md
lines 120-131 to use the active 0028_artifact_admission →
0029_shared_transactional_outbox lineage, or explicitly label the
0028_shared_transactional_outbox reference as historical. Apply the same update
or superseded-evidence label to the closing reconciliation at lines 355-362.
---
Nitpick comments:
In `@backend/tests/test_alembic.py`:
- Around line 122-219: Improve the synchronization in
_outbox_downgrade_writer_race by replacing the fixed asyncio.sleep(0.1) and
immediate downgrade.done() assertion with polling, such as checking pg_locks or
retrying with bounded backoff, until the downgrade reaches the expected
lock-wait state. Preserve the existing concurrency assertions and ensure the
test fails clearly if the state is not reached within a timeout.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 4a9de043-29dd-45b0-98b6-535a8b80a787
📒 Files selected for processing (24)
.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/ACTIVE_DOC_INVENTORY.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/AUTHORIZATION_HANDOFF.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/CHUNK_MAP.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/CONFORMANCE_MATRIX.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/DECISIONS.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/DISCOVERY.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/INTENT.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/JOINT_RELEASE_HANDOFF.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/PLAN.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/RUNTIME_VERIFICATION.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/SOURCE_MANIFEST.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/STATUS.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/chunks/WS-CON-001-02A-shared-outbox-persistence.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/chunks/WS-CON-001-11-hidden-release-readiness.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/reviews/WS-CON-001-02A-external-review-response.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/reviews/WS-CON-001-02A-internal-review-evidence.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/reviews/WS-CON-001-02A-pr-trust-bundle.md.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/reviews/WS-CON-001-02A-preimplementation-plan-review.mdbackend/alembic/versions/0029_shared_transactional_outbox.pybackend/app/modules/outbox/schemas.pybackend/tests/assertion_helpers.pybackend/tests/test_alembic.pybackend/tests/test_assertion_helpers.pybackend/tests/test_outbox.py
🚧 Files skipped from review as they are similar to previous changes (11)
- .agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/JOINT_RELEASE_HANDOFF.md
- .agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/SOURCE_MANIFEST.md
- .agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/ACTIVE_DOC_INVENTORY.md
- .agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/chunks/WS-CON-001-02A-shared-outbox-persistence.md
- backend/tests/assertion_helpers.py
- .agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/reviews/WS-CON-001-02A-internal-review-evidence.md
- .agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/RUNTIME_VERIFICATION.md
- backend/app/modules/outbox/schemas.py
- .agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/DISCOVERY.md
- backend/tests/test_outbox.py
- .agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/CHUNK_MAP.md
| merged REV planning PR #128, AUTH-09A/AUTH PR #140, and the earlier WS-XINT PR | ||
| #139 boundary. The runtime catalogue contains 74 PermissionIds and 65 ActionIds: |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Prevent wrapped PR references from becoming Markdown headings.
Leading references such as #139, #146, #153, and #156 are parsed as malformed ATX headings. Keep PR #<number> on the preceding line or escape the leading #.
.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/AUTHORIZATION_HANDOFF.md#L8-L9: keepPRReconcile AUTH ART REV and CON lifecycle boundaries #139`` inline..agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/DECISIONS.md#L225-L226: keepPRAdd bounded actor and identity-link administration reads #146and `PR `#153inline..agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/STATUS.md#L55-L55: keepPRClean-cut contributor attribution to canonical human actors #153`` inline..agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/STATUS.md#L69-L69: keepPRdocs(rev): split guide chronology and task locking contracts #156`` inline.
🧰 Tools
🪛 markdownlint-cli2 (0.23.0)
[warning] 9-9: No space after hash on atx style heading
(MD018, no-missing-space-atx)
📍 Affects 3 files
.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/AUTHORIZATION_HANDOFF.md#L8-L9(this comment).agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/DECISIONS.md#L225-L226.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/STATUS.md#L55-L55.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/STATUS.md#L69-L69
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
@.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/AUTHORIZATION_HANDOFF.md
around lines 8 - 9, Prevent wrapped PR references from being parsed as Markdown
headings by keeping each PR reference inline with its preceding text or escaping
the leading hash. Update AUTHORIZATION_HANDOFF.md lines 8-9 to keep PR `#139`
inline, DECISIONS.md lines 225-226 to keep PR `#146` and PR `#153` inline, STATUS.md
line 55 to keep PR `#153` inline, and STATUS.md line 69 to keep PR `#156` inline.
Source: Linters/SAST tools
| current main `8d5eb15b`, including the contributor foundation in AUTH PR #153, | ||
| AUTH-09D-B PR #152, ART-02B1 PR #151, REV PLAN2 PR #150, AUTH-09D-A PR #148, | ||
| REV-02 PR #147, REV-01 PR #145, AUTH-09C PR #146, ART PR #141, AUTH-09B PR | ||
| #143, REV planning PR #128, AUTH PR #140, and the underlying WS-XINT-001 | ||
| boundary from PR #139. PR #153 establishes canonical human `contributor_id` | ||
| lineage for TaskAssignment and Submission; it does not add CON authority, | ||
| service admission, review behavior, or outbox execution. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Keep all active trusted-main references on one baseline.
The active intent and plan still use 8d5eb15b, while the current trust bundle records 3b1d6379 after PR #156. Refresh or explicitly historical-label every affected site:
.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/INTENT.md#L13-L19: update the active SHA and merged-PR list..agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/PLAN.md#L5-L10: update the proposed-approach baseline..agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/PLAN.md#L167-L184: update the authorization-boundary baseline.
🧰 Tools
🪛 markdownlint-cli2 (0.23.0)
[warning] 16-16: No space after hash on atx style heading
(MD018, no-missing-space-atx)
📍 Affects 2 files
.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/INTENT.md#L13-L19(this comment).agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/PLAN.md#L5-L10.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/PLAN.md#L167-L184
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
@.agent-loop/initiatives/WS-CON-001-contribution-compensation-boundary/INTENT.md
around lines 13 - 19, Update the active trusted-main baseline from 8d5eb15b to
3b1d6379 and refresh the merged-PR list in INTENT.md lines 13-19; update the
proposed-approach baseline in PLAN.md lines 5-10 and the authorization-boundary
baseline in PLAN.md lines 167-184. Keep all three sites aligned, or explicitly
mark them historical if they must retain the prior SHA.
PR Trust Bundle: WS-CON-001-02A
Chunk
WS-CON-001-02A- Shared Transactional Outbox Persistence.Goal
Land feature-neutral shared PostgreSQL outbox truth and a caller-transaction
append participant, with enough persistence shape for 02B to add dispatcher
mechanics without another migration.
Risk: L1 infrastructure/data boundary; SLA P1.
Human-Approved Intent
The human explicitly started 02A after CON-01 merged. This chunk must remain
generic and authorization-neutral: AUTH owns every action, permission,
evaluator, service admission, and activation decision, while 02B and later
feature chunks own execution behavior.
Why It Changed
REV-owned lifecycle transactions need one generic durable event participant
that can flush into the caller's transaction without publishing, committing,
or inheriting feature authority. No such shared persistence boundary existed on
trusted main.
What Changed
0029_shared_transactional_outboxmigration after theART-owned
0028_artifact_admissionrevision.and flush-only service.
and state-shape tests.
naming 02B with a separate explicit start.
Design Chosen
counters, and initial eligibility time.
requires every immutable fact to match.
deterministically, and uses only the supplied
AsyncSession.app.core.hashingcanonicalJSON helper, takes one defensive deep payload snapshot before its first await,
and emits only stable input, conflict, or persistence errors with detached
payload-bearing validation/database exception contexts.
truncated.
authorization identifier, or product-domain mutation is present.
Scope Control
The committed diff is limited to the reviewed 02A migration, outbox module,
metadata registration, focused tests, initiative evidence, and one merge
intent. The user-owned local PDF deletion is excluded. No 02B dispatcher work
or protected product behavior is included.
Product Behavior
There is no new public or protected product surface. Existing review,
contribution, compensation, authorization, artifact, task, and project behavior
is unchanged; the new participant is infrastructure for later callers.
Alternatives Rejected
Acceptance Criteria Proof
on the exact bounded isolated outbox/migration row; outbox coverage is 95.73
percent against the 90 percent subsystem floor.
mapping compatibility repair preserves fail-closed secret graph inspection.
preserving AUTH's exact
0026downgrade/reupgrade behavior independently ofrepository head.
0029_shared_transactional_outbox, withparent
0028_artifact_admission.0028/ CON0029bounded row passes 73 tests with 32deselected after the Proxy repair and 95.90 percent focused outbox coverage.
3b1d6379; it changes planningcontracts only and adds no migration, runtime outbox seam, or CON authority.
0027rows are retained as historical pre-PR Clean-cut contributor attribution to canonical human actors #153 evidence;they do not replace the current
0028proof above or GitHub CI.with 95.73% outbox coverage against the 90% subsystem floor.
156.17 seconds; the reconciled outbox implementation retains 95.43% focused
coverage.
focused suite passed 76 tests in 243.28 seconds on the current tree.
identity-link lifecycle/concurrency suite passed 78 tests in 378.36 seconds.
to the full
0027head when AUTH refuses0026 -> 0025.0027_shared_transactional_outbox.required admin URL.
0027chain: passed.(4:55:41), with 85.35% repository coverage against the 78% floor.
f72bb6e, databaseworkstream_test_d513fb2f03b1, and the superseded Alembic head0026_shared_transactional_outbox; the superseded0027focused proof isretained above and GitHub CI must supply repository-wide proof after publication.
scans, and diff hygiene pass.
0027; PR Clean-cut contributor attribution to canonical human actors #153supersedes that revision with the current
0028proof above, and GitHub CImust pass after publication.
983b9e53. It changes onlyplanning/specification files, preserves the 02A runtime boundary, and updates
future CON/REV child gates. A two-hour suite on the prior head was stopped,
discarded, and is not counted.
1b5422fc. It adds the realS3-compatible adapter, MinIO service, SDK pins, CI gates, and a substantial
backend test delta without changing 02A code or migration. The 3-hour
7-minute run on the prior tree was stopped and discarded.
93dd3924. It activatesonly identity-link revoke/reactivate and adds AUTH route/test coverage, with
no migration or 02A boundary change. The one-hour run on the prior tree was
stopped and discarded.
8d5eb15b. Itclean-cuts TaskAssignment/Submission attribution to canonical human
contributor_id, adds writer revalidation, and owns0027. It changes noCON authority or outbox behavior; CON's migration is now the linear
0028child. Fresh bounded proof and exact-SHA internal review supersede the older
publication evidence, while the full suite remains GitHub CI-owned.
4 hours 15 minutes by human direction that repository-wide suites must run in
GitHub CI. Its metadata was removed and it is not counted. The existing
Backend full-suite job is the required exact-head repository proof.
Tests And Checks Run
The exact isolated PostgreSQL selector covers migration custody, rollback,
replay, collision races, payload privacy, and delivery-state constraints. The
separate helper suite covers deep secret-retention assertions. Ruff, Alembic
head, Markdown links, stale-contract scans, agent-loop tests, docstrings, and
git diff --checkalso pass.Test Delta
No existing test was deleted, skipped, weakened, or rewritten to accept broken
behavior.
Internal-review repairs add regression proof for one detached Pydantic
core-schema boundary across model methods and
TypeAdapter, valid Python/JSON/string-mode parity, hostile top-level and nested dict/list/string subclasses,
payload-free outbox traceback locals including idempotency conflicts, nested
payload mutation while reservation is blocked, payload-free database failures,
and caller rollback after an injected post-reservation failure. The shared deep-
retention assertion now inspects dict/list/string subclasses and slotted
dataclass state without invoking the tested hostile overrides. The exact
documented focused command generates fresh coverage before enforcing the
subsystem floor.
CI Integrity
No workflow, dependency, package script, test runner, lint/typecheck command,
coverage threshold, or CI configuration changed.
Repository-wide tests and the 78 percent repository coverage floor run only in
the existing GitHub Backend full-suite job. Local proof is bounded to focused
real-service tests, the 90 percent outbox coverage floor, Ruff, migrations, and
static gates. This changes execution location only: no test, assertion,
isolation control, or coverage threshold is waived.
Reviewer Results
9be9c88a19c4301f2b7ac606b6782604a48472bbpassed senior engineering, QA/test, security/auth, product/ops,
architecture, docs, reuse/dedup, test-delta, and CI-integrity review against
trusted main
3b1d63796c086f53fc2b0aeefe096387b82485ecwith no open findings and noopen reviewer sessions.
460573287270965d730c83f5f1e52f3acf1c0671.External Review
CodeRabbit review
8be695bd-33ce-4847-8bf1-905a130804ecposted five actionabledocumentation-consistency threads. The repair adds explicit reviewer tracks,
aligns AUTH counts, defines REV parent/child aliases, fixes REV-13C release
ownership, and fixes the REV-04B prerequisite. Its physical-purge suggestion is
deferred to separately started 02B because 02A forbids retention behavior and
its custody contract prohibits physical delete/truncate. GitHub Backend remains
in progress; external review does not replace internal review.
Remaining Risks
coverage floor on the published exact head.
contract; arbitrary per-call runtime option overrides are not a 02A API.
require a separately started 02B chunk.
no trigger-disable purge path is introduced into immutable 02A event truth.
Human Review Focus
implementing dispatcher behavior early?
commit and rollback orders?
envelope?
truth?
or product-domain boundary expansion?
Follow-Up Work
The same-initiative successor is
WS-CON-001-02B, Shared Outbox Dispatcher AndRecovery. It requires a separate explicit start after this PR merges and after
its AUTH/service prerequisites refresh from trusted main.
Human Merge Ownership
Only the human owner may approve and merge the specific 02A PR. Passing
reviewers, CI, or CodeRabbit do not authorize merge or the next chunk.
Summary by CodeRabbit
New Features
Bug Fixes
Tests
Documentation