Skip to content

feat: persist and reload live measurement sessions - #255

Closed
seonghobae wants to merge 12 commits into
mainfrom
cursor/measurement-session-persist-reload-6a63
Closed

seonghobae wants to merge 12 commits into
mainfrom
cursor/measurement-session-persist-reload-6a63

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 18, 2026 •

Copy link
Copy Markdown
Contributor

Why

After #225, persist/reload of a live measurement session remained the standing product Target. Buyers already grant purpose-specific consent and expect a later process or request to continue from that grant. In-memory aggregates disappear when the writer dies. Closed restore-reconcile work (#159, #158, #147, #133, #114, #124) is not a current landing. This PR implements the durable store.

What

  • Persist one live MeasurementSession as 3NF PostgreSQL 18 relations: assessment_participant, measurement_session, session_membership, session_consent_record, session_audit_event, and export_snapshot_pointer.
  • Reload restores membership, consent, audit, and the export-snapshot pointer. Named test persist_then_process_death_reloads_consent_audit_and_membership drops the writer connection, reloads on a new connection, and continues without re-consenting.
  • Consent and audit payloads are AES-256-GCM sealed with purpose measurement_session_persist. Authorization is ManageOwnSession only.
  • Exact replay is idempotent; rebinding any stored field fails closed.
  • ADR-0021, CHANGELOG, doctoring (APA 7th: W3C PROV-DM; NIST SP 800-53 Rev. 5 AU-11; AICPA TSC 2022). Identity-link history persist remains a later slice. This slice does not store scores.

Rebase

Rebased onto current main after #231 (d5443cdc1a52df8c7a34f0633a7353acfc79e008) left mergeable_state: dirty. Conflicted files were CHANGELOG.md and docs/TRACEABILITY.md only.

Coverage follow-up

f42ea4f4d58bf8e4598113f81457a992d097da26 passed Production line coverage (job 95580193494) and failed Production branch coverage 1425/1426 (job 95580193552). Format/lint/test/rustdoc, Strix, and coverage-evidence (job 95580299429) were green.

Remaining on that head, from job 95580193552 diagnose:

  • src/postgres_measurement_session.rs 51/52 — UNCOVERED_BRANCH ...:363:0:1
  • persist_sealed_row classify stored_identity == identity_ref && stored_nonce == nonce never ran false after an identity match. Consent content rebind keeps the derived nonce (same session_ref + event_ref); participant rebind short-circuits before the nonce comparison. Audit nonce-only rebind hits persist_audit_insert (575:0:1), not this arm.

This head adds persist_then_reload_rejects_consent_nonce_only_rebind: persist, process-death reload, then exact replay after only the stored consent nonce is rebound. That evaluates the identity-true / nonce-false AND short-circuit.

Local cargo +nightly-2026-08-01 llvm-cov --branch --lib --test postgres_measurement_session:

  • src/measurement_session.rs 1127/1127 lines, 40/40 branches
  • src/postgres_measurement_session.rs 639/639 lines, 52/52 branches
  • no remaining UNCOVERED_BRANCH on those files

Lane cut follows ADR-0004 / ADR-0007. This PR does not implement IRT, linking, scoring, or any psychometric kernel. It does not raise or reopen #159. It does not reopen identity-link #52. It is not stacked on #231 or #249.

Verification

  • cargo test --test postgres_measurement_session persist_then_reload_rejects_consent_nonce_only_rebind
  • cargo +nightly-2026-08-01 llvm-cov --branch --lib --test postgres_measurement_session
  • cargo fmt --all -- --check

Independent non-author approval and required checks on the unchanged exact head remain merge gates. Never self-approve.

Operator next action

Review persist/reload equality, purpose-limited authorization, and sealed consent/audit. After this lands, keep identity-link history as a later slice. Do not add scores or reopen #159 on this branch.

Open in Web Open in Cursor 

@cursor

cursor Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

cursor Bot pushed a commit that referenced this pull request Aug 18, 2026
Keep identity-link history as a later slice and do not treat
closed #159 as the persist vehicle.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Aug 18, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@seonghobae, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 18 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: bf7636f9-4478-498a-bb06-ff9dec2bda02

📥 Commits

Reviewing files that changed from the base of the PR and between 5544149 and c61bd99.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (21)
  • CHANGELOG.md
  • Cargo.toml
  • docs/QUALITY_ATTRIBUTES.md
  • docs/TRACEABILITY.md
  • docs/adr/0003-keyverse-identity-and-anonymous-participation.md
  • docs/adr/0015-persistence-and-transaction-boundaries.md
  • docs/adr/0021-measurement-session-persist-reload.md
  • docs/adr/README.md
  • docs/architecture/AS_BUILT_SCHEMA.md
  • docs/architecture/ERD.md
  • docs/architecture/SECURITY_AND_DATA.md
  • docs/doctoring/standards-and-evidence.md
  • migrations/0020_measurement_session.sql
  • src/anonymous_authorization.rs
  • src/lib.rs
  • src/measurement_session.rs
  • src/postgres_measurement_session.rs
  • tests/anonymous_session_command_authorization.rs
  • tests/documentation_architecture_contract.rs
  • tests/postgres_measurement_session.rs
  • tests/postgres_measurement_session_reference_integrity.rs
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/measurement-session-persist-reload-6a63

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

cursoragent and others added 8 commits August 18, 2026 02:53
Store participants, consent, audit events, and export snapshot
pointers in PostgreSQL so a buyer can continue after process
death without re-consenting. Consent and audit payloads are
AES-256-GCM sealed with purpose-bound keys; authorization stays
ManageOwnSession. No scores, IRT, linking, or identity-link
history are stored.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Keep identity-link history as a later slice and do not treat
closed #159 as the persist vehicle.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Authorize invalid stored refs, collapse SQL helpers so each
execute/query error path is reachable, and add real PostgreSQL
tests for process-death equality, field rebind, missing later
relations, and corrupt stored consent/audit evidence.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Collapse insert-or-classify so replay SELECT failures are
reachable, restore a clean session before field rebinds, and
add process-death, later-relation drop, and corrupt consent/audit
reload tests. Invalid stored refs and export-pointer construction
errors fail closed without a score kernel.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Hit audit-sort reload, overflow unix_ms, audit-only nonce rebind,
invalid stored tenant/created_at, aborted-transaction SHOW, and
remove the dead sealed_payload error arm.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Use one dyn classify predicate so unused monomorphizations cannot
leave uncovered JSON lines, and replace matches! fail arms with an
exhaustive error-name helper.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Run persist then process-death reload inside the crate tests so the
adapter instantiations in the lib binary are actually executed.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
LLVM JSON line totals treat lib and integration Display copies as
separate instantiations, so both must print every fail-closed variant.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
@cursor
cursor Bot force-pushed the cursor/measurement-session-persist-reload-6a63 branch from f7b5a2a to f42ea4f Compare August 18, 2026 02:53
Hit persist_sealed_row classify when participant identity matches and only the stored consent nonce was rebound.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 1a348ae77cc8244f7a5b4c85d17371493617b18b.

  • Head SHA: 1a348ae77cc8244f7a5b4c85d17371493617b18b

  • Workflow run: 32132935757

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (8 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (8 files)"]
  R1 --> V1["required checks"]
  Evidence --> S2["Docs (10 files)"]
  S2 --> I2["operator or user guidance"]
  I2 --> R2["Review risk: Docs (10 files)"]
  R2 --> V2["docs review"]
  Evidence --> S3["Test (3 files)"]
  S3 --> I3["regression suite"]
  I3 --> R3["Review risk: Test (3 files)"]
  R3 --> V3["targeted test run"]
Loading

@opencode-agent

opencode-agent Bot commented Aug 18, 2026 •

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

  • Head SHA: 1a348ae77cc8244f7a5b4c85d17371493617b18b
  • Workflow run: 32139446034
  • Workflow attempt: 1
  • Gate result: REQUEST_CHANGES (approval step)

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 1a348ae77cc8244f7a5b4c85d17371493617b18b.

  • Head SHA: 1a348ae77cc8244f7a5b4c85d17371493617b18b

  • Workflow run: 32139446034

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (8 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (8 files)"]
  R1 --> V1["required checks"]
  Evidence --> S2["Docs (10 files)"]
  S2 --> I2["operator or user guidance"]
  I2 --> R2["Review risk: Docs (10 files)"]
  R2 --> V2["docs review"]
  Evidence --> S3["Test (3 files)"]
  S3 --> I3["regression suite"]
  I3 --> R3["Review risk: Test (3 files)"]
  R3 --> V3["targeted test run"]
Loading

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 1a348ae77cc8244f7a5b4c85d17371493617b18b.

  • Head SHA: 1a348ae77cc8244f7a5b4c85d17371493617b18b

  • Workflow run: 32139446034

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (8 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (8 files)"]
  R1 --> V1["required checks"]
  Evidence --> S2["Docs (10 files)"]
  S2 --> I2["operator or user guidance"]
  I2 --> R2["Review risk: Docs (10 files)"]
  R2 --> V2["docs review"]
  Evidence --> S3["Test (3 files)"]
  S3 --> I3["regression suite"]
  I3 --> R3["Review risk: Test (3 files)"]
  R3 --> V3["targeted test run"]
Loading

@seonghobae

Copy link
Copy Markdown
Contributor Author

@opencode-agent Please review only exact head 4509cb8 against protected main 5544149. Earlier REQUEST_CHANGES reviews cited superseded heads or coverage evidence from those heads; do not transfer them. Report only actionable findings against this current SHA, and approve only from current-head evidence.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Updated the original branch to exact head c61bd99e9af727864434024f66d801d476c1d286 by merging protected main 5544149ca5dc55d2bfc3402cc59c03c44830de5f without force-pushing. The merge commit has parents 4509cb82 and 5544149c; no textual conflict was produced.\n\nFresh local evidence at this exact content: cargo fmt --all -- --check; cargo clippy --all-targets -- -D warnings; measurement-session persistence/reference-integrity, anonymous command authorization, integration-publisher, and documentation contract tests; TEST_DATABASE_URL=postgresql://seonghobae@localhost/postgres cargo test -q --all-targets (all targets passed); git diff --check; and CodeGraph sync. Exact-head GitHub checks are queued and the review decision reflects superseded OpenCode coverage evidence; no merge is claimed. This comment is not an approval.

@seonghobae

Copy link
Copy Markdown
Contributor Author

@opencode-agent Please review only exact head c61bd99e9af727864434024f66d801d476c1d286 against protected main 5544149ca5dc55d2bfc3402cc59c03c44830de5f. The measurement-session persistence branch was reconciled with a two-parent merge and local fmt, clippy, focused persistence tests, and all-targets tests are green; exact-head GitHub checks are queued. Earlier REQUEST_CHANGES evidence was coverage-only or from superseded heads and must not transfer. Report only actionable findings against this current SHA, and approve only from current-head evidence. This request is not an approval.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Current-head review recheck at c61bd99: the outstanding OpenCode CHANGES_REQUESTED record is coverage-only and cites superseded head 1a348ae. The branch already has the exact-head local measurement-session persistence, reference-integrity, anonymous command-authorization, integration-publisher, documentation, all-targets, format, clippy, rustdoc, and PostgreSQL evidence recorded in the prior reconciliation comments. No current-head code finding is identified; independent review and protected checks remain required.

Copy link
Copy Markdown
Contributor Author

Closing as a superseded/architecturally competing persistence line. Current protected main 3bb873f02d2e1639be49e2bc9ac998c158b48d3d implements and documents the accepted ADR-0005 AssessmentSession aggregate, assessment_session persistence/command history, persisted published-release start locking, and separate product-owned consent/session boundaries. This PR instead introduces a parallel MeasurementSession aggregate plus measurement_session/session_consent_record/session_audit_event storage and an unlanded ADR-0021, which would duplicate current lifecycle authority rather than extend the accepted state machine. Any still-useful restart/consent/audit requirement should be reconciled as a narrow slice onto the current AssessmentSession/consent/audit boundaries, not by reviving this alternate aggregate. Closing without merge does not claim those residual requirements are complete.

@seonghobae seonghobae closed this Aug 21, 2026
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.

2 participants