Skip to content

feat: move approval ownership into Casework - #1189

Open
jeremi wants to merge 31 commits into
mainfrom
codex/casework-approval-ownership
Open

jeremi wants to merge 31 commits into
mainfrom
codex/casework-approval-ownership

Conversation

@jeremi

@jeremi jeremi commented Sep 19, 2026

Copy link
Copy Markdown
Member

Summary

  • make Casework the sole owner of external and standalone review lifecycle state
  • integrate BReg through exact accepted-result bindings, durable recovery, and isolated multi-authority workers
  • publish maintained Rust, Node, Python, unified-client, schema, examples, and operational contracts
  • close final review gaps for producer isolation, accountability audit ordering, clock execution, source outage propagation, and bounded inbox continuation

Checks

  • products/casework/scripts/check-review-examples.sh
  • Casework PostgreSQL/HTTP: review 11/11, HTTP 4/4, migration 6/6, payment 2/2, BReg journey 1/1
  • BReg PostgreSQL: review executor 6/6, task grants 3/3
  • affected-package cargo clippy --locked --profile ci --all-targets -- -D warnings
  • cargo fmt --all -- --check and git diff --check
  • final independent Astra staff review: approved, no blocking findings

Notes

  • Registry App Kit adoption is explicitly deferred and excluded from this PR.
  • Migrations 0016 and 0017 are one unreleased delivery; an intermediate deployed v16-only clock state is unsupported.
  • OpenFn adaptor changes are proposed separately.

DCO

  • Every commit includes a Signed-off-by trailer.
  • I reviewed the submitted changes and am responsible for the contribution.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 19, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-20T05:08:48.620090Z 36d3c24 New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@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: 0b93e26eeb

ℹ️ 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 crates/registry-casework/src/review.rs Outdated
Comment thread crates/registry-breg/src/review_store.rs Outdated
Comment thread crates/registry-casework/src/http.rs Outdated
Comment thread crates/registry-casework/src/review.rs
Comment thread crates/registry-casework/src/review.rs Outdated
Comment thread crates/registry-casework-core/src/review.rs Outdated
Comment thread crates/registry-casework/migrations/0016_unified_reviews.sql Outdated
Comment thread crates/registry-breg/src/review_store.rs
Comment thread crates/registry-casework/src/review.rs Outdated
Comment thread crates/registry-casework/src/review.rs
Comment thread products/casework/scripts/generate_openapi.py Fixed

@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: 2b233fadf5

ℹ️ 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 crates/registry-breg/src/review_store.rs
Comment thread crates/registry-casework/src/review.rs Outdated
Comment thread crates/registry-casework/src/review.rs Outdated
Comment thread crates/registry-breg/src/review_store.rs Outdated
Comment thread crates/registry-casework/src/review.rs
Comment thread crates/registry-breg/src/postgres/mutation.rs
Comment thread crates/registry-breg/src/review_store.rs

@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: 0c7f56b118

ℹ️ 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 crates/registry-breg/src/review_store.rs
Comment thread crates/registry-breg/src/auth.rs
Comment thread crates/registry-breg/src/review_store.rs Outdated
Comment thread crates/registry-breg/src/review_store.rs Outdated
Comment thread crates/registry-breg/src/runtime_config.rs Outdated
Comment thread crates/registry-casework/src/config.rs Outdated
Comment thread crates/registry-casework/migrations/0016_unified_reviews.sql Outdated
Comment thread crates/registry-casework/src/problem.rs
Comment thread crates/registry-casework/src/review.rs Outdated

@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: fe1e197292

ℹ️ 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 crates/registry-casework/src/review.rs
Comment thread crates/registry-casework/src/review.rs
Comment thread crates/registry-casework/src/review.rs
Comment thread crates/registry-casework/src/review.rs Outdated

@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: 0d9bb9c59e

ℹ️ 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 crates/registry-casework/src/review.rs Outdated
Comment thread crates/registry-casework/src/review.rs
Comment thread crates/registry-casework/migrations/0016_unified_reviews.sql
Comment thread crates/registry-casework/migrations/0016_unified_reviews.sql
Comment thread crates/registry-casework/src/review.rs Outdated
Comment thread crates/registry-casework/src/runtime.rs Outdated
Comment thread crates/registry-casework/src/review.rs Outdated
Comment thread crates/registry-breg/src/runtime_config.rs Outdated
Comment thread crates/registry-casework/migrations/0016_unified_reviews.sql

@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: e176f29bf6

ℹ️ 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 crates/registry-breg/src/runtime_config.rs Outdated
Comment thread crates/registry-casework/src/review.rs Outdated
Comment thread crates/registry-breg/src/review_store.rs Outdated
Comment thread products/casework/scripts/generate_openapi.py Outdated
Comment thread .github/workflows/ci.yml
Comment thread crates/registry-stack-client-node/casework/client.d.ts Outdated

@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: e84a9246a7

ℹ️ 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 crates/registry-casework/src/http.rs Outdated
Comment thread crates/registry-casework-core/src/config.rs
Comment thread crates/registry-casework-client/src/client.rs Outdated
A hosted kind may declare a closed-object resultSchema beside its
displaySchema, and each outcome may declare resultRequired. A requester
may narrow declared fields per item at create time through
resultConstraints (enum, oneOf with titles, minimum/maximum,
minLength/maxLength), where every choice and bound must already satisfy
the pinned kind schema: the compiled schema is the authority and the
subset rules never re-implement JSON Schema semantics. A decision may
then carry a result that validates against the schema and the accepted
narrowing.

All new fields are serde-optional and skip serialization when absent,
so existing policies, snapshots, and request payloads keep byte-identical
canonical forms and digests: the starter kind digest is pinned by test at
sha256:6f9fbf8b801dda6527aece6bbf34cdc7d0b8ff7899d9e012367302aff1aa3139.

Five validation reasons join the catalogue (result_not_declared,
result_required, field_not_declared, constraint_invalid,
constraint_violated) with header-safe instance paths that fall back to
the payload root prefix when a field name is not header-safe.

Deviation from spec section 3.7 noted for the reviewers of the whole
change: hosted validation failures are HTTP 400 request.invalid with the
registry-casework-validation-path/-reason headers in this tree, exactly
like the existing nine reasons; the section's 422 wording is drift.

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Migration 0015 adds result_constraints to casework_hosted_items, result
to casework_hosted_terminal_events, and result_digest to
casework_hosted_accountability. The items payload-erasure CHECK now also
forbids surviving constraints once the requester payload is erased;
constraints are optional at creation, so they may be NULL while the
payload is live but never present after erasure.

Create stores accepted constraints after re-checking them against the
pinned snapshot, and they ride the create idempotency hash via the
canonical request bytes. Decide validates the result against the pinned
snapshot and the item's stored constraints, persists the result on the
terminal event, its sha256-over-canonical-JSON digest on the
accountability record, and the result verbatim in the completed history
detail. The requester projection, staff work-item context, terminal
page, and accountability record each expose their new field, and the
erasure clock nulls constraints with the rest of the payload.

The Rust, Python, and Node clients register the five new validation
reasons, keeping the cross-catalogue gate green.

Security note (data minimization and erasure): the result is Casework's
own decision data and rides the same terminal clock as the display
payload; the accountability row keeps only a digest of the canonical
result until its own clock expires, and both are deleted by the existing
retention sweep. Spec section 3.7 drift noted in the core commit: these
failures answer 400 request.invalid with validation headers, not 422.

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
The hosted PostgreSQL suite gains three tests: constraints flow from
create through the requester projection, staff work-item context, a
narrowed decision, the terminal page, and an accountability digest equal
to sha256 over the canonical result JSON; a create replay under the same
idempotency key with different constraints conflicts while a refused
payload leaves the key reusable; and the result payload erases on the
terminal clock with the rest of the requester payload while the digest
survives until the accountability clock deletes its row.

The standalone HTTP journey gains a wire test asserting each of the five
new validation reasons arrives as HTTP 400 request.invalid with the
snake_case reason and instance path headers, using an in-code
result-capable kind so the shipped example stays result-free.

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
The generator documents resultRequired on outcomes, resultSchema on the
kind policy and staff context, resultConstraints on the create request,
requester projection, and staff context, result on decisions and
completed terminal results, and resultDigest on accountability records,
each optional and bounded by the same 16 KiB canonical and depth-16
payload limits as display. The hard terminal-fields check and the bound
markers now pin the result payload constants too.

The configure page evidence anchor follows the renamed
check_closed_object_schema helper so the docs anchor gate stays green.

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Clippy prefers the strict bound form without the plus-one offset, and the
migration ledger tests now expect head 15 after the hosted result
migration.

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
…elds

Regenerate the @registrystack/client facade typings via
release/scripts/sync-registry-client-node.py so the optional hosted
result surface (resultRequired on outcomes, resultSchema and
resultConstraints on kind policy, work-item context, create requests,
and requester items, result on decisions and completed terminal
results, resultDigest on accountability records) reaches the unified
package exactly as the maintained registry-casework-client-node
binding declares it.

Security note (data minimization review): the facade keeps result
payloads on the requester terminal-results surface only; the
accountability surface exposes the sha256 result digest, not the
result itself, matching the Rust and maintained Node typings.

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
… clients

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
…ment

The hosted validation-reason header enum on the four hosted validation
routes still named only the original nine reasons after the structured
result work, so a generated client would reject the server's own 400
refusals for result_not_declared, result_required,
field_not_declared, constraint_invalid, and constraint_violated.
Append the five codes in HostedValidationReason declaration order and
regenerate the committed document; generate_openapi.py --check
passes and both result routes now carry the fourteen-value enum.

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
…acks

Two review findings on the result validation core.

Bound containment (check_constraint_bounds) compared constraint bounds
only against keywords written directly on the property object, so a
property like {"type":"integer","$ref":"#/$defs/bounded"} or one
hiding its bound behind allOf accepted a widening constraint at create
and left the kind schema to arbitrate at decide. Bound keywords are now
refused unless the property subschema is plain inline: no $ref sibling
and no allOf/anyOf/oneOf, whose effective bounds are not statically
visible. Choices (enum/oneOf values) on such properties are unchanged
because they are validated by instance against the compiled schema.

The sanitized-path fallback in HostedValidationError::new was the
literal $.display, so a result error under a field name that cannot
travel in a response header (a space, a non-ASCII byte) was mislabeled
$.display while display was valid. The fallback is now scoped:
display validation keeps $.display, result validation falls back to
$.result, and constraint errors fall back to $.resultConstraints.

Tests: bound_constraints_require_plain_inline_properties and
result_errors_fall_back_to_the_result_root_not_display; the existing
inline-bound and display-fallback tests stay green.

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Spec 3.5 requires the If-Match, idempotency, deciding-profile, and
claim checks to run before any result validation, but the decide
transaction validated the result first: an officer submitting an
invalid result without a claim, with a stale revision, or under a
reused idempotency key learned a 400 validation refusal instead of the
semantic error, and an unclaimed item leaked schema feedback to a
caller who could not decide it at all.

The store now runs result validation after the deciding-profile
re-check, the idempotency replay/conflict, the revision/state If-Match,
and the holder check, inside the same FOR UPDATE transaction; the
check returns the typed StoreError::HostedValidation so the wire keeps
the bounded reason and path headers. The service drops its eager
request check, keeps the hosted_policy_for_actor gate so an officer
without deciding authority still learns only that the item is not
found, and converts the store's typed refusal to
ServiceError::HostedValidation, preserving the existing error shape.

Security note (data minimization review): the reorder means validation
feedback now requires deciding authority plus a live claim on the item
at the expected revision, so result-schema probing cannot use
validation refusals as an oracle on items the caller cannot decide.

Test: decide_semantic_checks_precede_result_validation pins the
conflict, stale-revision, and idempotency-conflict precedence over
validation; the existing wire-reason and results-flow tests stay
green.

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
@jeremi
jeremi force-pushed the codex/casework-approval-ownership branch from e84a924 to c203181 Compare September 20, 2026 01:33

@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: c2031810c1

ℹ️ 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 crates/registry-casework/src/http.rs Outdated
Comment thread crates/registry-breg/src/review_store.rs Outdated
Comment thread crates/registry-casework/migrations/0016_unified_reviews.sql Outdated
Comment thread crates/registry-breg/src/review_store.rs
Comment thread products/casework/scripts/generate_openapi.py Outdated
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>

@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: 7ff65a6945

ℹ️ 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 crates/registry-casework/src/http.rs Outdated
Comment thread products/casework/scripts/generate_openapi.py Outdated
Comment thread products/casework/scripts/generate_openapi.py Outdated
Comment thread crates/registry-casework/src/review.rs
Comment thread crates/registry-casework/src/task_grants.rs
Comment thread .github/workflows/ci.yml
Comment thread crates/registry-casework/src/review.rs
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>

@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: aa8b509ae5

ℹ️ 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 crates/registry-casework/src/review.rs
Comment thread crates/registry-casework/src/review.rs
Comment thread crates/registry-casework/src/review.rs
Comment thread crates/registry-casework/src/review.rs Outdated
Comment thread crates/registry-breg/src/api/mod.rs Outdated
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>

@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: fd9f00340c

ℹ️ 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 crates/registry-casework/src/review.rs Outdated
Comment thread crates/registry-casework/src/config.rs Outdated
Comment thread crates/registry-casework-core/src/config.rs Outdated
Comment thread crates/registry-breg/src/review_store.rs Outdated
Comment thread crates/registry-casework/src/review.rs Outdated
Comment thread crates/registry-casework/src/runtime.rs Outdated
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>

@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: 36d3c24523

ℹ️ 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 on lines +398 to +400
Err(_) => {
budget_exhausted = true;
break;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve continuation when the first source read times out

When the first candidate's source preflight reaches the global page deadline, examined has already been incremented, but this branch exits before assigning continuation. The later examined == 0 outage check is therefore skipped and the endpoint returns an empty successful page with nextCursor: null, even though unexamined tasks remain; clients can interpret that as the end of the inbox and miss work. Return SourceUnavailable or a resumable cursor for the timed-out candidate.

AGENTS.md reference: AGENTS.md:L124-L126

Useful? React with 👍 / 👎.

Comment on lines +1576 to +1577
WHERE request_entity_id=$1 AND request_id=$2 AND proposal_version=$3
AND state='cancelling'",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Fence cancellation updates by lease ownership

In an HA deployment, the cancellation HTTP timeout may equal the 30-second lease, so another replica can reclaim the row while the first request is still finishing. A stale failure then matches only the submission identity and state='cancelling', clears the replacement worker's lease, and immediately makes the row reclaimable for another duplicate cancellation; carry the claimed lease value or an ownership token through both cancellation completion paths.

Useful? React with 👍 / 👎.

Comment on lines +56 to +58
let token = std::str::from_utf8(secret.expose_secret())
.map_err(|_| RuntimeError::CompletionConfiguration)?
.to_owned();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Validate completion bearer tokens before starting

If a referenced token contains a trailing newline, whitespace, non-ASCII text, or another HTTP-header-invalid byte, the secret resolver and this UTF-8 conversion accept it and the runtime starts normally. bearer_auth then records an invalid-header error, every delivery attempt fails locally, and the outbox eventually becomes exhausted without ever contacting the receiver; validate the resolved value with the shared BearerToken type during startup.

Useful? React with 👍 / 👎.

Comment on lines +3186 to +3189
AND ($3::uuid IS NULL OR (occurred_at,event_id)>(
SELECT occurred_at,event_id FROM casework_review_history
WHERE request_id=$1 AND event_id=$3
))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject unknown review-history cursors

When a caller supplies a well-formed cursor that is absent or belongs to another request, this scalar subquery returns no row, making the tuple comparison unknown for every history entry. The endpoint consequently returns a successful empty page with no continuation even when later entries exist, silently truncating traversal; resolve and validate the cursor before running the page query and return the cursor-expired/invalid response when it cannot be found.

Useful? React with 👍 / 👎.

Comment on lines +3239 to +3241
FROM casework_review_clock_occurrences o
LEFT JOIN casework_review_tasks t ON t.task_id=o.task_id
WHERE o.request_id=$1 ORDER BY o.clock_id,o.scope,o.clock_occurrence_id",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Stop serving review clocks after terminal retention

When accountabilityDays exceeds terminalDays, terminal cleanup leaves clock occurrences and the minimized request row until the later accountability deadline, and this query has no result_available_until check. A requester can therefore continue reading retained subject-clock correlations—including the exact source, subject type and subject ID plus timing—after the declared request-payload deadline; fresh evidence beyond the earlier source-visibility fix is that these retained rows remain directly queryable here after tasks, history, context, and results are erased.

Useful? React with 👍 / 👎.

Comment on lines +115 to +117
if complete.value.subject != request.subject
|| &complete.value.submission_digest != expected_submission_digest
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Bind accepted reviews to the requested kind

If Casework or an intermediary returns the correct subject and submission digest but a policy binding for another review kind, this maintained client accepts it because it never checks policy.id against request.kind or validates the policy binding. The returned value then becomes the expected policy for subsequent result validation, so Rust, Node, and Python callers can accept a terminal result governed by the wrong policy instead of reporting a protocol failure; apply the same accepted-response checks as registry-review-client.

Useful? React with 👍 / 👎.

Comment on lines +1030 to +1031
AND (state='source_facts_missing'
OR (state='running' AND next_action_at<=now()))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Back off source-facts-missing review clocks

When an activity clock is waiting for a holiday document, its occurrence remains source_facts_missing, and this selector makes it due unconditionally on every two-second maintenance pass. Updating updated_at—including the explicit defer path—never makes that state temporarily ineligible, so each task repeatedly performs an authoritative source read and database evaluation until the holiday data appears; with many missing clocks or a slow source this can saturate the source and delay the same maintenance loop's retention work. Gate this state on a retry timestamp or an updated_at backoff.

Useful? React with 👍 / 👎.

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