mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-01 15:35:12 +01:00
fix(server): schedule Teams consent expiry from saved deadlines
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
9a06e4a6ba
commit
5ddb4543ed
12 files changed
+457
-68
No files matched your search
@@ -0,0 +1,61 @@
|
||||
# Teams consent expiry and idle work
|
||||
|
||||
Unused Teams file consent now uses the shared delivery coordinator and scheduler.
|
||||
Existing `chat_teams_file_transfers` rows own its state. There is no new table,
|
||||
independent timer, provider request or external-wake capability.
|
||||
|
||||
## Obligation and trigger
|
||||
|
||||
Only `consent_pending`, `awaiting_consent` and `upload_pending` rows are eligible.
|
||||
Each uses its saved `expiresAt`. Startup reconstructs these rows in 100-row UUID
|
||||
pages. Committed writes reload the affected transfer ID. The service registers
|
||||
intent before insertion and its central versioned update, within the existing
|
||||
transaction. Nested savepoints wait for outer settlement. The shared work-signals
|
||||
protocol retains ambiguous outcomes; callers do not manage recovery wrappers.
|
||||
|
||||
Configured endpoints, completed history, unknown outcomes and active transport
|
||||
attempts do not keep this worker scanning. Pending consent retains its actual
|
||||
future deadline. PostgreSQL submillisecond timestamps round up to the next
|
||||
millisecond; checking a deadline does not extend it.
|
||||
|
||||
## Expiry and recovery
|
||||
|
||||
At the deadline, the worker reloads the current row and delegates to the existing
|
||||
Teams protocol owner. That owner locks publication then transfer, verifies the
|
||||
current authority digest, rechecks phase and expiry, and updates the transfer
|
||||
and publication projection in the same transaction. It does not send a consent
|
||||
card, upload data or send a file-info card. Lock waits remain bounded. A changed
|
||||
phase is re-evaluated; a deleted or settled row removes the cached obligation.
|
||||
|
||||
A failed load, lock or projection retains retry work. Corrupt rows do not starve
|
||||
other transfers or companies. Errors emitted by this worker are generic and do
|
||||
not contain SQL parameters, private transfer envelopes or provider capabilities.
|
||||
The shared worker owns coalescing, batching, dirty hints, drain/resume and shutdown.
|
||||
Shutdown joins an in-flight expiry; restart reconstructs the saved deadline.
|
||||
|
||||
The explicit `expireAndRecover` diagnostic method retains combined behavior.
|
||||
Production periodic maintenance now selects and executes abandoned attempts only.
|
||||
Attempt recovery is a separate remaining migration. Unknown provider outcomes
|
||||
remain quarantined; this change does not authorize a resend.
|
||||
|
||||
## Ownership and limitations
|
||||
|
||||
Provider phase selection and expiry live in the Teams module and existing Teams
|
||||
transfer service. Shared app wiring only registers the owner and lifecycle gate.
|
||||
The queue topic is a notification namespace, not a new durable queue. Other
|
||||
providers and the shared scheduler receive no Teams protocol policy.
|
||||
|
||||
Supported producers use the process's owning DB client. Independent SQL writers
|
||||
or another process require their own wake contract. On-use authorization remains
|
||||
with the protocol. Cloud eligibility and external alarm coverage are unchanged:
|
||||
a future in-process deadline cannot wake stopped compute. This proves the changed
|
||||
worker can become quiet, not fleet savings or complete instance suspension.
|
||||
|
||||
## Verification
|
||||
|
||||
Real PostgreSQL protocol cases cover all three phases, producer activation,
|
||||
rollback and held outer commit, restart, pre-deadline quiet, timestamp precision,
|
||||
projection rollback, fairness, drain/resume and shutdown. Production integration
|
||||
registers the worker before Board publication and proves expiry cancels the
|
||||
publication without another provider call. Existing authority, publication and
|
||||
consent suites remain covered. See the [audit and failure ledger](plans/2026-10-25-teams-consent-expiry-sleep-audit.md).
|
||||
@@ -1358,3 +1358,16 @@ cleanup and retention workers had 37 passing cases. CI/reviews remain required.
|
||||
Next owner audit splits Teams unused-consent expiry from abandoned send/upload
|
||||
attempt recovery, preserving one reason per PR. Company deletion cleanup policy
|
||||
and the earlier E2E failure remain unresolved completion duties.
|
||||
|
||||
|
||||
## Slice 26: Teams unused-consent expiry
|
||||
|
||||
The Teams owner now selects existing unused-consent phases and their saved expiry
|
||||
through scoped deadline work. Production maintenance retains only abandoned
|
||||
attempts; these are the next distinct reason. No new table or Cloud alarm policy
|
||||
is included. The [audit](2026-10-25-teams-consent-expiry-sleep-audit.md) records
|
||||
222 unique selected passing cases, workspace types/build, and initial fixture
|
||||
failures. Publication and fresh remote checks/review remain required.
|
||||
Parent #17586 Actions/security/Greptile pass at 250fca6cff; Paperclip Review is
|
||||
still running. The original full inventory, older E2E failure, deletion-policy
|
||||
finding and master reconciliation remain outstanding. No stack PR is merged.
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Baseline: voice call-report PR #17586 at 250fca6cff.
|
||||
Branch: codex/sleep-26-teams-consent-expiry.
|
||||
Status: audit; implementation, local acceptance, publication and remote gates pending.
|
||||
Status: implemented and locally verified; publication and remote gates pending.
|
||||
|
||||
## Separate reasons
|
||||
|
||||
@@ -68,3 +68,54 @@ cannot expire consent. Full stack checks and master reconciliation remain requir
|
||||
#17586 is published, attached, and locally verified; remote CI/reviews are pending.
|
||||
#17580's company deletion policy finding and #17490's E2E cancellation failure are
|
||||
still unresolved. No original recurring-server obligation is removed from scope.
|
||||
|
||||
## Implementation and acceptance
|
||||
|
||||
The Teams owner now registers a scoped deadline worker. The existing service
|
||||
signals before issue/update writes, including caller-owned resolution transactions.
|
||||
Startup pages eligible rows; transfer hints reload only that primary key. The
|
||||
owner rechecks expiry with the original publication/transfer lock order and
|
||||
atomic projection. The old periodic selection and execution now cover attempts
|
||||
only. No schema or external wake contract changes are included.
|
||||
|
||||
Local verification at the slice-26 implementation:
|
||||
|
||||
- 65 transfer protocol cases pass on a fresh external PostgreSQL database.
|
||||
These include 102-entry paging/fairness with one corrupt row, shutdown joining
|
||||
a held projection, the three consent phases, precision, rollback, restart,
|
||||
drain/resume, private-error redaction and the remaining maintenance boundary.
|
||||
- The earlier five-suite run passed 206 cases: then-63 transfer cases and 143
|
||||
publication, consent, consent-runtime and app-wiring cases. The final transfer
|
||||
run adds two cases. The latest app-wiring assertions pass all 16 cases again.
|
||||
- 14 selected real production integration cases pass. This includes registration
|
||||
before an actual Board publication, post-commit wake, saved deadline, pre-expiry
|
||||
SQL quiet, atomic expiry/publication cancellation, no extra provider requests,
|
||||
and the existing Teams current-authority/Board-transfer group. The other 1,411
|
||||
integration cases were skipped, not passed.
|
||||
- Together these are 222 unique selected cases. Workspace `pnpm -r typecheck`
|
||||
and `pnpm build` pass. Server typechecking excludes test files; it is not proof
|
||||
that the test files were statically checked.
|
||||
- Local full `pnpm test:run` remains unclaimed because this host's embedded
|
||||
PostgreSQL setup failed earlier in the stack. Full remote gates are required.
|
||||
No live Teams tenant or deployed host-suspension qualification is claimed.
|
||||
|
||||
Failure ledger: the first protocol run had two invalid fixtures. A direct phase
|
||||
mutation set attempt expiry without its required paired attempt ID; another
|
||||
assertion treated the public ISO expiry string as a Date. Both were corrected,
|
||||
then all five suites passed on a fresh database. The first production expiry
|
||||
assertion expected a failed publication; the existing correct expiry projection
|
||||
is cancelled. The corrected test and the authority group pass. These were test
|
||||
expectation/setup errors, not weakened production contracts or hidden retries.
|
||||
|
||||
Evidence logs: `/tmp/sleep26-teams-tests.log` (initial two fixture failures),
|
||||
`/tmp/sleep26-teams-fixed-tests.log` (206 pass),
|
||||
`/tmp/sleep26-teams-final-tests.log` (65 pass),
|
||||
`/tmp/sleep26-producer-tests.log` (initial projection-state assertion),
|
||||
`/tmp/sleep26-production-acceptance.log` (14 pass),
|
||||
`/tmp/sleep26-final-wiring.log` (16 pass), and
|
||||
`/tmp/sleep26-workspace-{types,build}.log` (pass).
|
||||
|
||||
Parent #17586 at 250fca6cff has passing Actions, security and Greptile checks;
|
||||
Paperclip Review is still running at the latest inspection. This does not clear
|
||||
older stack findings or imply merge authority. Refreshed master is b7dc594bfa;
|
||||
final whole-stack reconciliation is still required.
|
||||
Reference in new issue
Block a user