Skip to content

Daily tech-debt sweep — 2026-11-02 - #2242

Merged
peterdrier merged 85 commits into
mainfrom
codex/daily-debt/2026-11-02
Nov 2, 2026
Merged

peterdrier merged 85 commits into
mainfrom
codex/daily-debt/2026-11-02

Conversation

@peterdrier

Copy link
Copy Markdown
Owner

Ledger: 7 → 6 open rows. Closed CONSENT-1 as D6 hygiene. No rows added.

The original work window has ended. The final discovery pass selected no additional verified batch. The last commit is a5fdb5388, and the working tree is clean on codex/daily-debt/2026-11-02. Nothing was pushed or published.

Pre-approved contract changes

  • D1: Shifts SearchVolunteerVisibleRotas(query, eventId, max, ct) → (query, eventId, ct), allowing ranking before the caller’s limit.
  • D1/D13: Gate ExecuteAsync(string, long? = null, CancellationToken = default) → ExecuteAsync(string, long, CancellationToken = default), requiring the persisted scan timestamp.
  • D1: Legal SyncAllDocumentsAsync(ct = default) → (ct = default, ICollection<Exception>? failures = null), collecting failures while completing remaining work.
  • D1/D2: Internal Teams ApplyMemberRoleChangesAsync(changes, ct) returns Task<IReadOnlyList<Guid>> instead of Task<int>, identifying actual saved role changes.
  • D1: Preapprovals ClaimAsync, ReleaseAsync, and ConsumeAsync each add optional Action<Func<CancellationToken, Task>>? afterCommit = null after their existing four parameters. Expenses owns the transaction; the collector keeps audit and notice logic in Preapprovals while delaying execution until commit.
  • D1/D2: Extracted internal ShiftSignupNotices, SurveyTranslationFiller, RideshareNotices, and TeamGoogleGroupMemberships owners. Public entry-point signatures remain unchanged; no new public interface or DI registration.
  • Removed unused IUserEmailService methods GetNobodiesTeamEmailAsync, GetPrimaryEmailAsync, and GetVerifiedEmailsForUserAsync after checking production consumers.
  • Replacement-provisioning coordination changes are private; its public signatures remain unchanged.

Needs Peter

CENTRAL-105: Expenses currently persists Holded document IDs and creates capped, multi-line purchase documents. Existing IHoldedWrite deliberately returns outcomes without IDs, so replacing connector calls alone would break retries and reconciliation. The maintenance policy requires this ownership transition to have a dedicated scope.

Yes/no: authorize a dedicated Expenses phase retaining Task ExpenseHoldedPublisher.PublishAsync(Guid outboxEventId, ExpenseReportDto report, Instant now, CancellationToken ct) while moving publication to the key-based Holded write contract and preserving caps, attachments and retry behavior?

Cumulative production changes

There are 76 net substantive improvements across 84 local commits. Counts below record validation at each commit. A means the 32 architecture checks; P means resource parity. Scoped test runs included their builds.

Finance and canonical recipient data

Round / commit Production change Validation
1 · a41315fa7 Finance journal posting uses existing Holded write outcomes, preserving amounts and retry markers; partially addresses CENTRAL-105. Finance 510; A
8 · fcd4ee2dc Users notification targets share canonical UserInfo.Email selection without changing raw reporting cohorts. Users 853; A
9 · 65453074b Ticket transfer notices reuse canonical recipient snapshots. Tickets 462; A
12 · 046f003f9 Finance audits remote Holded account creation before saving its local registry row. Finance 511; A
58 · 6507a21f7 Governance email workflows reuse resolved recipient snapshots. Governance 493; A
59 · 96fcc3a7e Survey invitations, reminders and previews reuse recipient snapshots. Surveys 483; A
60 · d59f96819 Campaign sends and resends reuse resolved recipient email. Campaigns 110; A
61 · 568d1dae9 Preapproval email delivery reuses loaded recipients. Preapprovals 154; A
62 · efb088d55 Grant notices reuse snapshots while retaining address-lookup recovery after an earlier metadata lookup fails. Grants 75; A
63 · d4f4acebb Feedback replies and Issues comment emails reuse reporter snapshots. Feedback 78; Issues 226; A
64 · 649b814a7 SEPA payout notices reuse existing member snapshots. Finance 511; A
65 · c9a4bba83 Expense approval notices reuse the submitter snapshot. Expenses 536; A
66 · 24073b082 Workgroup lifecycle emails reuse recipient snapshots. Workgroups 415; A
67 · c72b7d35d Composer self-send resolves its recipient once. Email 348; A
70 · 262c153fc MailerLite previews match synchronization’s canonical email selection. MailerLite 188; A
72 · 2b82c7c42 SEPA cap and amount parsing reject grouping separators that could inflate comma-decimal input. Finance 515; A
73 · 0c226c96a Workgroup budget forms reject ambiguous grouping separators. Workgroups 417; A

Identity, lifecycle and data correctness

Round / commit Production change Validation
3 · dbe69dc5d Consent cooldown considers reminder timestamps across merged identities. Consent 258
6 · bbc99efd7 Account erasure attempts all contributors and reports incomplete runs; completed erasure survives confirmation-email failure. Users 847
7 · c158a9114 Suspension jobs record one run outcome, including empty sweeps. Users 850
21 · 5e0ad1413 Membership expiry resolves audit display context before changing the tier; commit ordering finalized in round 82. Governance 491; A
24 · 217fa0825 Lifecycle inbox updates finish independently after committed state changes. Users 858; A
25 · b9b320a7c Deletion requests commit the pending marker and access revocations together; rollback repairs provisional cache state. Users 862; Auth 170; Teams 581; A
27 · 104ab955d Google erasure suspends every verified Workspace mailbox belonging to the raw account before deleting local identities. Google 599; A
28 · 5eeb97353 MailerLite erasure stays on the raw account instead of following a tombstone to its survivor. MailerLite 185; A
31 · 49088c8db Rideshare request answers stay within their event. Rideshare 235
32 · 4633dffb6 Ride matching distinguishes riders from drivers. Rideshare 235
33 · 41c647e0b Survey active audiences use account state, excluding fake and deletion-pending accounts. Surveys 482; A
34 · be41a1a90 Profile setup mode follows Bare/missing-profile state on reads and writes. Users 868
35 · 72a13c267 Survey response and GDPR exports share answer context while preserving missing-definition fallbacks. Surveys 483
37 · 02eb5b256 Gate mirror jobs use persisted scan time instead of job execution time. Gate 114; A
38 · 229a76f29 Pending-deletion dates use the UI culture. Gdpr 68; Base date 6; P
49 · e6277e960 Legal versions persist pending re-consent batches, retaining unfinished recipients and stable delivery identities across unchanged retries. Consent 263; A; EF checks and review
54 · 513be8883 Pending merge lookup compares literal email addresses within pending requests for the target. Users 874; A
55 · 515248083 Google resource lookup compares literal group addresses and exact numeric identities. Google 602; A
56 · bd230d514 Group linking checks the resolved Google identity before adding an already-active resource. Google 605; A
57 · aab786b2f Google readers reuse the existing active-resource-type query. Google 605; A
68 · 5c1290aae A committed deletion request still reports success when confirmation lookup or delivery fails. Users 876; A
69 · 166a2e545 Suspensions still receive audit attempts when prepared user metadata is missing. Users 877; A; revised in 82
83 · 0224eb002 Replacement provisioning emits creation/profile-repair and email-deletion audits after its outer commit. Rejected commits retain original state without success audits. Users 877; Tickets 462; MailerLite 188; A

Notices, jobs and audit boundaries

Round / commit Production change Validation
2 · 8eae0cfef Notification delivery shares emitter validation, recipient handling and persistence. Notifications 120; A
5 · 911b674eb Renewal reminders complete remaining recipients before reporting delivery failures. Governance 488
10 · 62025863f Scheduled MailerLite syncs fail when required work remains incomplete. MailerLite 183; A
11 · 60423915a System-team changes are audited before Google provisioning can fail. Teams 580; A
13 · 1f2ec2d89 Failed preapproval reminders remain eligible for retry. Preapprovals 152; A
17 · bf86271f3 Survey reminders report incomplete sweeps and reuse delivery identities. Surveys 480; A
18 · 5e62d032e Renewal reminders reuse delivery identities after failed stamps. Governance 488; A
19 · 34b5232f9 Assembly emails reuse deliveries within each announced deadline. Governance 490; A
20 · 88cfbf2f1 Re-consent reminders reuse deliveries within each cooldown cycle. Consent 260; A
23 · 96db008d9 Camp membership decisions share notice preparation and failure handling. Camps 620
26 · 4918250fd Email outbox jobs record failed runs. Email 348
39 · 4be1ad17f Feedback triage shares persistence-before-audit ordering. Feedback 78
41 · 4fa647601 Coordinator membership notices use recipient languages. Teams 589; P; format placeholders checked
42 · 4c964995b Coordinator shift notices use recipient languages. Shifts 1094; P; format placeholders checked
43 · e66daf01e Issues resolve canonical recipients and actors before self-exclusion and culture grouping. Issues 222; A
44 · 08eab5e0e Role lookup failures do not suppress remaining saved-issue notices. Issues 226; A
46 · f18d52155 Preapproval manager notices continue after individual delivery failures. Preapprovals 154
48 · 268e2d489 Assembly sweeps finish remaining delivery and closure work before reporting failures. Governance 493; A
50 · 65aa8dfeb Legal sync reports failures after completing successful document work and pending notifications. Consent 267; A
75 · 2f7870457 Role assignment notices use recipient languages. Auth 180; A; P; format placeholders checked
77 · 4c683667b Coordinator reconciliation returns actual changed membership IDs and audits/reports saved changes only. Teams 593; A; revised in 82
81 · 2a85af346 AuditLog suppresses caller ambient transactions through context disposal; file deletions retain independent best-effort audits. AuditLog 76; Camps 620; Containers 109; CityPlanning 224; A
82 · 3e17a4383 Expiry, deletion-request, merge-rejection and reminder audits follow business commits; unsupported audit-exception collectors removed. Governance 493; Users 878; Preapprovals 154; Teams 591; A
84 · a5fdb5388 Expenses commits report/grant metadata before running Preapprovals-owned audits and inbox completion. Rollback discards completion; post-commit notice failures remain best-effort. Expenses 536; Preapprovals 162; A

Workflows, ownership and executable tooling

Round / commit Production change Validation
4 · 342840b4b Removed obsolete single-consumer Consent helpers. Consent 258
14 · 0bc70d4f5 Public-surface reporting excludes internal contracts. Python 11; real report
15 · a48ed789c Events, Teams, Camps and Shifts rank search matches before caller limits. Events 589; Teams 581; Camps 620; Shifts 1087; Search 30; A
16 · 4da0e24d2 People search selects strongest matches before its safety cap. Users 855; Search 30; A
22 · abf5e7b80 Public-surface reporting includes Base interfaces. Python 12; real report
30 · efd49eca2 Shift signup notices have an internal owner separate from mutations. Shifts 1087; A
36 · b02c148cf Survey translation preparation has an internal owner separate from authoring. Surveys 483; A
40 · 3086f1b73 User summary display ordering belongs to presentation. Users 868; display-sort check
45 · 3e0b84621 Pending-consent display ordering belongs to rendering consumers. Consent 260; Scanner 11; Agent 253; A
47 · 48b04e686 Shift dashboard metrics exclude historical ticket orders. Shifts 1095; A
51 · a05e48f5a Rideshare interest notices have an internal owner separate from mutation rules. Rideshare 235; A
52 · 9e62f5894 Notification search treats wildcard characters literally. Notifications 128; A
53 · 809c89111 Shift tag search and reuse compare literal names. Shifts 1101; A
71 · 728d3807e Teams Google Group membership calculation has one internal owner. Teams 589; A
74 · d7fc08e66 Stripe recovery belongs to Store’s existing payment-ingestion owner, preserving locks and retries. Store 434; A

Superseded work, support and hygiene

  • Rounds 76 (9763e0cd0) and 78 (0c46f930e) added audit-exception collectors based on exceptions the real AuditLog service deliberately swallows. Round 82 removed those collectors and exception-only tests.
  • Rounds 79 (e0080d109) and 80 (1f44d27ab) coupled file-deletion metadata with audit transactions. Round 81 restored the documented independent, best-effort audit boundary.
  • These four rounds are excluded from the substantive count.
  • Round 29, 8fb4f79fd, removed unused email projection APIs as supporting cleanup. Users 861, Tickets 462 and architecture checks passed; it is not counted separately.
  • CONSENT-1 closure and stale invariant-document cleanup are hygiene.
  • Reporter follow-ups 14/22, search follow-ups 15/16, and renewal follow-ups 5/18 each count as one improvement.
  • Final discovery added no commit and no substantive-fix count.

Migration and validation limits

Round 49 generated 20261102063239_PersistReConsentNotificationBatches through EF in Consent’s own LegalDbContext. It adds a nullable batch identifier without a backfill. Pending-model checks, generated SQL inspection, migration checksums and the required migration review passed. No migration was applied to a database.

Transaction regressions verify ambient scope, completion status and ordering. Round 83 additionally exercises rollback using transaction-enlisted fake stores and forced commit rejection. Round 84 verifies commit/abort completion behavior for claim, re-stamp, release and consumption, plus all four Expenses callers. These tests do not prove PostgreSQL rollback behavior.

All new localized copy covers en, es, de, it, fr and ca. Owning invariant docs were updated. No new endpoints, public interfaces, services or privilege grants were introduced.

Humans.Integration.Tests was never run. The wrapper’s final full build and non-integration gate remain pending.

Remaining rows, exclusions and batch boundaries

  • Initial migration checks found CENTRAL-89, CENTRAL-92, CENTRAL-93, CENTRAL-94 and CENTRAL-95 still live, with pending counts 87, 2136, 2059, 1854 and 3405 respectively. Retirement remains unsafe until their existing migration workflows complete; no runtime data was changed.
  • CENTRAL-105 remains partially open for the dedicated Expenses transition described above.
  • Recipient changes used section-sized batches to preserve distinct retry, fallback and failure semantics. Feedback/Issues shared one compatible batch.
  • Finance and Workgroup amount parsing had different refusal semantics. Vendor JSON and persisted journal-reference formats were excluded from that form-input correction.
  • Business ordering and historical reporting cohorts were preserved; only verified display-order or current-event defects were changed.
  • Admin-timed operational races were excluded under D8.
  • Direct audit-call moves, replacement provisioning, and Expenses→Preapprovals completion were separate batches because they have different transaction owners and nested effects. The known deferred audit candidates were handled through rounds 82–84.
  • Final bounded discovery found no actionable display-sort baseline entries or Calendar/Tickets TODO/HACK debt. Grants helper candidates had callers in partial files; Rideshare/Grants ordering served export chronology or event selection. The Finance reconciliation loader already delegates calculation to its existing owner. No new verified batch was selected before cutoff.

Total recorded work: 11h 2m 54s active, 12h 1m 18s wall time, including final verification after the deadline. The goal is complete and the checkout is ready for the wrapper’s validation/publication gate.

Runner outcome

Work deadline reached

Ledger

Open rows: 7 → 6 (net -1).

Goal time: 12h; actual worker time: 722m 34s; total run through validation: 726m 21s.

Runner validation: build pass, tests pass; Humans.Integration.Tests excluded.

Advance CENTRAL-105 using the existing write contract, retaining retry tags and journal amount markers. Audit confirmation outcomes instead of connector references. Close CONSENT-1 under the standing policy against controller-policy pinning tests.
Share preference filtering, copy limits and persistence between individual sends and role broadcasts while preserving their resolution scopes. Remove the redundant single-notification repository write.
Read the latest reminder stamp across each survivor's identity chain instead of ignoring stamps left on merged-away accounts. Keep historical rows and existing export and erasure behavior intact.
Keep required-consent projection in its sole service owner now that the cache delegates to it. Inline the single-use chat-terms name in its document definition and retain the existing shaping assertions through the service boundary.
Collect email and sent-stamp failures while attempting the remaining recipients, then fail the job so failed reminders can retry. Preserve best-effort in-app notices and successful reminder stamps.
Attempt every due account, then propagate collected anonymization failures for job visibility and retry. Keep post-erasure confirmation delivery failures terminal and preserve their identity-safe logging.
Count every completed sweep once, including empty candidate sets and unchanged users. Remove run-success accounting from the domain service while retaining its per-member suspension metrics.
@peterdrier

Copy link
Copy Markdown
Owner Author

Nightly cleanup spend

Estimated Standard API list-price equivalent; not subscription billing. Each session includes its linked subagents.

Cleanup — 01a1998e-800f-7511-bd35-1fce25ffec59

Codex spend estimate - root 01a1998e-800f-7511-bd35-1fce25ffec59
Workspace: /home/drierp/.humans-debt-runner/clone

Agent                           Model        Level   Task turns  Responses  Est. cost  Tokens   In/cache/write/out     Note
------------------------------  -----------  ------  ----------  ---------  ---------  -------  ---------------------  ----
/root                           gpt-6.1-sol  medium  85          2058       $67.1670   505.15M  3.48M/500.65M/0/1.01M      
/root/review_consent_migration  gpt-6-luna   medium  1           7          $0.0058    234.4K   29.9K/202.9K/0/1.6K        

Agents: 2    Responses: 2065    Tokens: 505.38M    Estimated priced total: $67.1728

Caveats:
- Task turns are outer agent tasks; each can contain many model responses and tool calls.
- Responses count per-response usage records; costs sum those records independently of task-turn count.
- API-equivalent estimate using Standard list rates checked 2026-09-23 (GPT-6.1 Sol: 2026-09-30); rates can change and subscription billing may differ.
- Cached input is priced separately; visible cache writes use 1.25x the input rate.
- Reasoning tokens are included in output_tokens and are not charged twice.
- The estimate omits tool fees, regional/processing adjustments, and long-context premiums.
- Usage records can arrive late, so an active session may be incomplete.

@github-actions github-actions Bot added the db PR includes EF Core migration label Nov 2, 2026
@github-actions

github-actions Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

PR Surface Report

Compared 3b63d660...783a8e69. Scored with reforge 0.32.0.

Summary: 287 changed file(s) | EF migrations: 1 added file(s), max 1/1 per context

Reforge Surface Score

metric base head delta
total 61659 61540 -119
surface 14511 14388 -123

Section Deltas

section base head delta
Surveys 2671 2582 -89
Users 5175 5142 -33
Consent 1148 1174 +26
Holded 1329 1308 -21
Preapprovals 688 706 +18
Shifts 5571 5588 +17
Expenses 1864 1877 +13
Rideshare 601 614 +13
Notifications 521 511 -10
Workgroups 1695 1685 -10
Tickets 2390 2382 -8
Campaigns 442 435 -7
Finance 2623 2630 +7
Grants 460 453 -7
GoogleIntegration 4264 4258 -6
Issues 792 786 -6
Teams 3418 3412 -6
Governance 2215 2210 -5
Camps 2595 2591 -4
Store 1062 1066 +4
Email 953 950 -3
Feedback 425 422 -3
Auth 535 537 +2
Gate 502 501 -1

Section Size & Complexity Deltas

section LOC delta files delta classes delta cognitive p95 delta
AuditLog +4 0 0 0
Auth +4 0 0 0
Campaigns -3 0 0 0
Camps -17 0 0 0
Consent +19 -2 -2 0
Email +7 0 0 0
Events +1 0 0 0
Expenses +15 0 0 0
Feedback -1 0 0 0
Finance -1 0 0 0
Gate -1 0 0 0
GoogleIntegration -10 0 0 0
Governance +15 0 0 0
Grants +1 0 0 0
Issues -3 0 0 0
MailerLite +2 0 0 0
Notifications -34 0 0 -1
Preapprovals +55 0 0 0
Rideshare +36 +1 +1 0
Scanner +1 0 0 0
Shifts +33 +1 +1 0
Store +5 0 0 0
Surveys +2 +1 +1 0
Teams +7 +1 +1 0
Tickets -1 0 0 0
Users -10 0 0 +1
Workgroups -2 0 0 0
Corpus +124 +2 +2 0

Corpus is the solution-wide rollup (same source as Corpus Size & Complexity below), not a sum of the section rows above - cognitive p95 in particular doesn't compose across sections.

Rule Deltas

rule base head delta
classSize 4112 4013 -99
crossSectionReadInterface 3942 3852 -90
methodComplexity 18090 18176 +86
oneImplementationInterface 336 312 -24
sectionSize 7173 7187 +14
exportedReadMethod 2920 2908 -12
methodCount 16830 16833 +3
methodParameterOverflow 482 485 +3

Corpus Size & Complexity

metric base head delta
locProd 181019 181143 +124
maxClassLoc 1976 1885 -91
classes 3187 3189 +2
files 2348 2350 +2
cyclomatic max 77 78 +1
methods 7707 7706 -1

At head: largest class SurveyService, most complex method DevelopmentDashboardSeeder.SeedAsync.

Published Write Surface

17 of 51 sections publish write capability, 51 interfaces (0).

Interface Surface

Added interface methods

IPreapprovalWrite

  • Task<PreapprovalWriteResult> ClaimAsync(Guid grantId, Guid expenseReportId, Guid actorUserId, CancellationToken ct, Action<Func<CancellationToken, Task>>? afterCommit = null)
  • Task<PreapprovalWriteResult> ConsumeAsync(Guid grantId, Guid expenseReportId, Guid actorUserId, CancellationToken ct, Action<Func<CancellationToken, Task>>? afterCommit = null)
  • Task<PreapprovalWriteResult> ReleaseAsync(Guid grantId, Guid expenseReportId, Guid actorUserId, CancellationToken ct, Action<Func<CancellationToken, Task>>? afterCommit = null)

Diff Size

bucket added deleted
code 1537 1456
migrations 42 4
tests 2781 754
docs 188 118
other 191 10

New Files

  • src/Sections/Humans.Consent/Data/Migrations/20261102063239_PersistReConsentNotificationBatches.Designer.cs
  • src/Sections/Humans.Consent/Data/Migrations/20261102063239_PersistReConsentNotificationBatches.cs
  • src/Sections/Humans.Rideshare/Services/RideshareNotices.cs
  • src/Sections/Humans.Shifts/Services/ShiftSignupNotices.cs
  • src/Sections/Humans.Surveys/Services/SurveyTranslationFiller.cs
  • src/Sections/Humans.Teams/Services/TeamGoogleGroupMemberships.cs
  • tests/Humans.MailerLite.Tests/Jobs/MailerLiteAudienceSyncJobTests.cs

EF Migrations (OK)

  • src/Sections/Humans.Consent/Data/Migrations/20261102063239_PersistReConsentNotificationBatches.cs

Repaired: 5e0ad14 Audit each membership expiry within its tier mutation — Governance data-access.md now says the TierDowngraded audit follows the commit (3e17a43 moved it).
Repaired: b9b320a Commit deletion requests and access revocations atomically — IAccountDeletionService XML doc no longer claims the audit commits with the marker.
Fixed: dotnet format whitespace violations failing the code-quality check (10 files).

Review-round: 1

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186neA51VTAAwfAjB4ssCdZ
@peterdrier

Copy link
Copy Markdown
Owner Author

Debt review

84 commits: 78 GOOD · 4 GOOD-superseded · 2 REPAIRED · 0 REVERTED. Round-1 commit 783a8e69 (two doc repairs + whitespace fixes for the failing code-quality check). Build 0 errors; full non-integration suite green.

Commit verdicts (84)
sha claim verdict reason
d59f968 Campaign recipient snapshots GOOD Same address via GetUserInfosAsync; docs updated
568d1da Preapproval recipient snapshots GOOD Same snapshot address; coverage kept
efb088d Grant snapshots + email recovery GOOD Fallback lookup only on failure; recovery test added
d4f4ace Feedback/Issues reporter snapshots GOOD Behaviour preserved; failure test re-aimed
649b814 SEPA payout member snapshots GOOD Merged checks, same skip behaviour
c9a4bba Expense submitter snapshot GOOD Behaviour preserved
24073b0 Workgroup recipient snapshots GOOD Lookup failure still logged and skipped
c72b7d3 Composer self-send single lookup GOOD One lookup; 422 on missing address
6202586 MailerLite scheduled sync fails on incomplete work GOOD Job throws for Hangfire retry; sync idempotent
6042391 System-team audit before Google provisioning GOOD Net shape correct after 3e17a43
046f003 Holded account creation audited before registry save GOOD Remote create audited even if upsert throws
1f2ec2d Failed preapproval reminders retry GOOD Reminder-only failure propagation; doc updated
0bc70d4 Surface report excludes internal contracts GOOD Regex requires public; test covers it
a48ed78 Rank search hits before limits GOOD Top-N selection, not display sort; docs updated
4da0e24 People search strongest matches before cap GOOD Score ordering before Take; test added
bf86271 Survey reminder sweeps report incomplete, reuse IDs GOOD Unique delivery id; idempotent outbox
4918250 Email outbox jobs record failed runs GOOD Records failure and rethrows; doc updated
104ab95 Suspend every verified Workspace mailbox before erasure GOOD Raw snapshot, distinct verified addresses; abort kept
5eeb973 MailerLite erasure scoped to raw account GOOD Real fix: tombstone erase no longer hits survivor
8fb4f79 Remove unused email projection APIs GOOD No callers remain; docs updated
efd49ec Shift signup notices internal owner GOOD Verbatim move to internal class, no new DI
49088c8 Rideshare answers within their event GOOD Event check with legacy fallback; tests
4633dff Riders vs drivers in matching GOOD Request-bound interest matches only its request
41c647e Survey audiences from account state GOOD Matches glossary; docs and tests updated
be41a1a Profile setup mode from account state GOOD Mode derived from account, not posted flag
08eab5e Issue notices survive role lookup failures GOOD Per-role best-effort; doc and test
3e0b846 Pending-consent display order to consumers GOOD Both consumers sort; tests pin order
f18d521 Preapproval manager fanout continues past failures GOOD Per-recipient isolation; reminders still rethrow
48b04e6 Shift dashboard excludes historical orders GOOD Reuses IsCurrentEvent like Gate/Surveys
268e2d4 Assembly sweep reports failures after remaining work GOOD Stamped rows + stable ids prevent duplicates
e6277e9 Persist re-consent batches GOOD Nullable column, EF-generated migration in LegalDbContext
65aa8df Legal sync reports failures after doc work GOOD Transient failure in aggregate is tested intent; logs stay Warning
a05e48f Rideshare interest notices internal owner GOOD Verbatim internal move
9e62f58 Notification search literal GOOD In-memory ordinal match; test added
809c891 Shift tag names literal GOOD In-memory ordinal match on small table
513be88 Pending merge emails literal GOOD Reuses GetPendingAsync
5152480 Legacy Google group addresses literal GOOD Reuses GetActiveByTeamIdAsync; tests
bd230d5 Reject links to already-active resolved group GOOD Real fix; tested
aab786b Reuse active-resource-type query GOOD Duplicate repo method removed
6507a21 Governance recipient snapshots GOOD Equivalent address; failure paths still tested
96fcc3a Survey recipient snapshots GOOD Equivalent address
5e62d03 Renewal reminder delivery ids GOOD Stable per-application id
34b5232 Assembly email deliveries per deadline GOOD Key re-arms on extension
88cfbf2 Re-consent delivery ids per cooldown GOOD Anchored to last successful stamp
5e0ad14 Membership expiry audit REPAIR Net shape fine; data-access.md still says audit is in-transaction
abf5e7b Base interfaces in surface report GOOD Path roots extended; test matches
96db008 Camp decision notices consolidated GOOD Behaviour identical
217fa08 Lifecycle inbox after commit GOOD Post-commit with None token, Camps pattern
b9b320a Deletion request + revocations atomic REPAIR Contract XML doc still says audit commits together
a41315f Finance journal via IHoldedWrite GOOD Same connector call; retry tag kept
8eae0cf Notification delivery in emitter GOOD Removed AddAsync has no callers
dbe69dc Consent cooldown across merges GOOD Real fix; doc and test
342840b Remove single-consumer consent helpers GOOD Inlined identically; tests at service boundary
911b674 Renewal failures after fanout GOOD Stamped reminders excluded on retry
bbc99ef Incomplete deletion runs fail GOOD Completed accounts leave due set
c158a91 Suspension metric at job boundary GOOD Empty sweep now records success
fcd4ee2 Canonical UserInfo email for notifications GOOD Same fallback chain
6545307 Ticket transfers canonical email GOOD Equivalent to GetPrimaryEmailAsync
5c1290a Committed deletion survives confirmation failure GOOD Best-effort post-commit confirmation
166a2e5 Suspension audits despite missing metadata GOOD Net: audit first, collector removed later
262c153 MailerLite preview canonical email GOOD Duplicate helper removed
728d380 Teams Google Group calc internal owner GOOD Verbatim internal move
2b82c7c SEPA rejects grouping separators GOOD type=number inputs; no valid input lost
0c226c9 Workgroup budgets reject grouping separators GOOD Same fix; tests
d7fc08e Stripe recovery to Store ingestion owner GOOD Verbatim move; idempotent path
2f78704 Role notices in recipient language GOOD Six cultures, prefixed keys, tests
9763e0c System-team audit collector GOOD-superseded Removed by 3e17a43
4c68366 Coordinator reconciliation audits saved changes GOOD Real audit gap; internal signature
0c46f93 Team deactivation audit collector GOOD-superseded Fully reverted by 3e17a43
e0080d1 Camp deletion + audit together GOOD-superseded Undone by 2a85af3
1f44d27 Image/container deletion + audit together GOOD-superseded Undone by 2a85af3
2a85af3 AuditLog suppresses ambient transaction GOOD Stops ghost audits; tested
3e17a43 Audits after business commits GOOD Required after 2a85af3; docs updated
0224eb0 Replacement provisioning audits after outer commit GOOD Skipped on rollback
a5fdb53 Preapproval effects after expense commit GOOD Completions run post-commit only
72a13c2 Survey answer context shared GOOD Null-tolerant; GDPR test added
b02c148 Survey translation internal owner GOOD Verbatim internal move
02eb5b2 Gate mirror persisted scan time GOOD Real fix; D13 covers signature change
229a76f Pending-deletion date UI culture GOOD Shared ToDate() formatter
4be1ad1 Feedback triage save-before-audit GOOD Three copies folded
3086f1b User summary ordering to presentation GOOD display-sort-in-controllers rule
4fa6476 Coordinator membership notices localized GOOD Six cultures; placeholders match
4c96499 Coordinator shift notices localized GOOD 16 keys x6 cultures
e66daf0 Issues resolve recipients before self-exclusion GOOD Fixes unresolved-actor compare

Spot-check overturned one worker REPAIR: 65aa8dfe (transient GitHub errors joining the job aggregate) is tested intent with logs kept at Warning — GOOD.

Data migrations. No commit retires one. Live https://humans.nobodies.team/api/data-migrations, fetched this run: finance.iban-to-payment-details, consent.profile-review, tickets.event-participations, email.communication-preferences all "pending":0,"done":true; google.workspace-identities "pending":3405,"done":false. The PR body's pending counts for CENTRAL-89/92/93/94 (87/2136/2059/1854) don't match production — those four retirement rows are now unblocked for the next sweep (CENTRAL-95 still blocked).

/fix triage. No review threads on the PR at round 1 — nothing to triage.

thread finding verdict
— none —

Needs Peter. CENTRAL-105 not elevated: having IHoldedWrite return document ids for the Expenses phase is a D1 shape and the row already carries the phase plan. Stays in the ledger as partial.

Issues filed: none.

Ledger: 6 → 6 open rows this review (runner: 7 → 6).

Rounds spent: 1 of 3 · pushed 783a8e69

Recommendation: merge.


Generated by Claude Code

@peterdrier
peterdrier merged commit 8a85e6b into main Nov 2, 2026
7 checks passed
@peterdrier
peterdrier deleted the codex/daily-debt/2026-11-02 branch November 2, 2026 20:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

db PR includes EF Core migration

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants